From 137fb7e30b360d27a6b83ea1193bc8bac3e54581 Mon Sep 17 00:00:00 2001 From: seto Date: Mon, 11 Nov 2024 12:15:59 +0900 Subject: [PATCH] update --- CSManager/CSManager.csproj | 2 +- Crystallography.Controls/.editorconfig | 4 + .../ChemicalFormulaInputControl.cs | 3 + .../ColorControl.Designer.cs | 13 +- Crystallography.Controls/ColorControl.cs | 39 +- .../Crystal/BoundControl.cs | 17 +- .../Crystal/FormScatteringFactor.Designer.cs | 715 +++--- .../Crystal/FormScatteringFactor.cs | 50 +- .../Crystal/FormScatteringFactor.ja.resx | 179 ++ .../Crystal/FormScatteringFactor.resx | 1287 +++++++++- .../Crystal/PoleFigureControl2.Designer.cs | 159 ++ .../Crystal/PoleFigureControl2.cs | 361 +++ .../Crystal/PoleFigureControl2.ja.resx | 199 ++ .../Crystal/PoleFigureControl2.resx | 442 ++++ .../Crystallography.Controls.csproj | 15 +- Crystallography.Controls/DataSet.Designer.cs | 6 +- Crystallography.Controls/DataSet.cs | 25 + Crystallography.Controls/DataSet.xsd | 140 +- .../Numeric/NumericBox.cs | 1 + .../Wave/WaveLengthControl.cs | 27 +- Crystallography/BetheMethod.cs | 337 +-- Crystallography/Crystal/Crystal.cs | 165 +- Crystallography/Crystal/PolyCrystal.cs | 2165 ++++++++--------- Crystallography/Crystallography.csproj | 20 +- Crystallography/Detector/Ring.cs | 30 +- Crystallography/ExtensionMethods.cs | 217 +- Crystallography/FindParameter.cs | 2 +- Crystallography/Images/ImageIO.cs | 29 + Crystallography/Images/ImageProcessor.cs | 10 +- .../Mathematics/{Geometriy.cs => Geometry.cs} | 4 +- Crystallography/Miscellaneous.cs | 48 + Crystallography/MonteCarlo.cs | 170 ++ Crystallography/Profile.cs | 2 +- Crystallography/Stereonet.cs | 8 +- Crystallography/Symmetry/SymmetryOperation.cs | 110 + Crystallography/UniversalConstants.cs | 51 +- Crystallography/WaveProperty.cs | 5 + 37 files changed, 5373 insertions(+), 1684 deletions(-) create mode 100644 Crystallography.Controls/.editorconfig create mode 100644 Crystallography.Controls/Crystal/FormScatteringFactor.ja.resx create mode 100644 Crystallography.Controls/Crystal/PoleFigureControl2.Designer.cs create mode 100644 Crystallography.Controls/Crystal/PoleFigureControl2.cs create mode 100644 Crystallography.Controls/Crystal/PoleFigureControl2.ja.resx create mode 100644 Crystallography.Controls/Crystal/PoleFigureControl2.resx rename Crystallography/Mathematics/{Geometriy.cs => Geometry.cs} (99%) create mode 100644 Crystallography/MonteCarlo.cs diff --git a/CSManager/CSManager.csproj b/CSManager/CSManager.csproj index f25e447..7deeb51 100644 --- a/CSManager/CSManager.csproj +++ b/CSManager/CSManager.csproj @@ -2,7 +2,7 @@ WinExe - net8.0-windows10.0.22621.0 + net8.0-windows10.0.26100.0 true 2024.7.4.1116 2024.7.4.1116 diff --git a/Crystallography.Controls/.editorconfig b/Crystallography.Controls/.editorconfig new file mode 100644 index 0000000..be539c9 --- /dev/null +++ b/Crystallography.Controls/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# WFO1000: A property should determine its property content serialization with the DesignerSerializationVisibilityAttribute, DefaultValueAttribute or the ShouldSerializeProperty method +dotnet_diagnostic.WFO1000.severity = silent \ No newline at end of file diff --git a/Crystallography.Controls/ChemicalFormulaInputControl.cs b/Crystallography.Controls/ChemicalFormulaInputControl.cs index a2169d4..1a1655d 100644 --- a/Crystallography.Controls/ChemicalFormulaInputControl.cs +++ b/Crystallography.Controls/ChemicalFormulaInputControl.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Windows.Forms; namespace Crystallography.Controls; @@ -7,6 +8,7 @@ public partial class ChemicalFormulaInputControl : UserControl { private bool standardMode = true; + [DefaultValue(true)] public bool StandardMode { set @@ -18,6 +20,7 @@ public bool StandardMode } private bool weightMode = true; + [DefaultValue(true)] public bool WeightMode { diff --git a/Crystallography.Controls/ColorControl.Designer.cs b/Crystallography.Controls/ColorControl.Designer.cs index d90be1e..0dffb01 100644 --- a/Crystallography.Controls/ColorControl.Designer.cs +++ b/Crystallography.Controls/ColorControl.Designer.cs @@ -40,6 +40,7 @@ private void InitializeComponent() // // pictureBox // + pictureBox.BackColor = System.Drawing.SystemColors.Control; pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; pictureBox.Location = new System.Drawing.Point(0, 0); pictureBox.Margin = new System.Windows.Forms.Padding(0); @@ -53,16 +54,19 @@ private void InitializeComponent() // labelHeader // labelHeader.AutoSize = true; + labelHeader.BackColor = System.Drawing.SystemColors.Control; + labelHeader.Font = new System.Drawing.Font("Segoe UI Symbol", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0); labelHeader.Location = new System.Drawing.Point(0, 0); labelHeader.Margin = new System.Windows.Forms.Padding(0); labelHeader.Name = "labelHeader"; - labelHeader.Size = new System.Drawing.Size(0, 23); + labelHeader.Size = new System.Drawing.Size(0, 15); labelHeader.TabIndex = 2; // // flowLayoutPanel // flowLayoutPanel.AutoSize = true; flowLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + flowLayoutPanel.BackColor = System.Drawing.SystemColors.Control; flowLayoutPanel.Controls.Add(labelHeader); flowLayoutPanel.Controls.Add(pictureBox); flowLayoutPanel.Controls.Add(labelFooter); @@ -75,18 +79,21 @@ private void InitializeComponent() // labelFooter // labelFooter.AutoSize = true; + labelFooter.BackColor = System.Drawing.SystemColors.Control; + labelFooter.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0); labelFooter.Location = new System.Drawing.Point(24, 0); labelFooter.Margin = new System.Windows.Forms.Padding(0); labelFooter.Name = "labelFooter"; - labelFooter.Size = new System.Drawing.Size(0, 23); + labelFooter.Size = new System.Drawing.Size(0, 17); labelFooter.TabIndex = 3; // // ColorControl // - AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F); + AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; AutoSize = true; AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + BackColor = System.Drawing.SystemColors.Control; Controls.Add(flowLayoutPanel); Font = new System.Drawing.Font("Segoe UI Symbol", 12.1875F); Margin = new System.Windows.Forms.Padding(0); diff --git a/Crystallography.Controls/ColorControl.cs b/Crystallography.Controls/ColorControl.cs index 578f6a9..e7d8321 100644 --- a/Crystallography.Controls/ColorControl.cs +++ b/Crystallography.Controls/ColorControl.cs @@ -10,6 +10,8 @@ public partial class ColorControl : UserControl { public event EventHandler ColorChanged; + + [DefaultValue(typeof(FlowDirection),"LeftToRight")] [Category("Appearance property")] public FlowDirection FlowDirection { @@ -22,16 +24,20 @@ public FlowDirection FlowDirection } } + [DefaultValue(typeof(Size),"24,24")] [Category("Appearance property")] public Size BoxSize { get => pictureBox.Size; set => pictureBox.Size = value; } + [DefaultValue("")] [Localizable(true)] public string ToolTip { set => toolTip.SetToolTip(pictureBox, value); get => toolTip.GetToolTip(pictureBox); } + [DefaultValue("")] [Category("Header/footer text")] [Localizable(true)] public string HeaderText { set { labelHeader.Text = value; labelHeader.Visible = value != ""; } get => labelHeader.Text; } + [DefaultValue("")] [Category("Header/footer text")] [Localizable(true)] public Font HeaderFont { set => labelHeader.Font = value; get => labelHeader.Font; } @@ -44,6 +50,7 @@ public FlowDirection FlowDirection [Localizable(true)] public string FooterText { set { labelFooter.Text = value; labelFooter.Visible = value != ""; } get => labelFooter.Text; } + [Localizable(true)] [Category("Header/footer text")] public Font FooterFont { set => labelFooter.Font = value; get => labelFooter.Font; } @@ -52,52 +59,68 @@ public FlowDirection FlowDirection [Category("Header/footer text")] public Padding FooterMargin { set => labelFooter.Margin = value; get => labelFooter.Margin; } + + [DefaultValue(false)] + [Category("Color")] + public bool Inversion { set; get; } = false; + [Category("Color")] - public Color Color { set => pictureBox.BackColor = value; get => pictureBox.BackColor; } + public Color Color + { + set => pictureBox.BackColor = value; + get { + var color = pictureBox.BackColor; + return Inversion ? Color.FromArgb(color.A, 255 - color.R, 255 - color.G, 255 - color.B): color; + } + } [Category("Color")] - public int Argb { set => pictureBox.BackColor = Color.FromArgb(value); get => pictureBox.BackColor.ToArgb(); } + public int Argb + { + set => pictureBox.BackColor = Color.FromArgb(value); + get => Color.ToArgb(); + } [Category("Color")] public int Red { set { if (value >= 0 && value < 256) pictureBox.BackColor = Color.FromArgb(value, pictureBox.BackColor.G, pictureBox.BackColor.B); } - get { return pictureBox.BackColor.R; } + get => Inversion ? 255 - pictureBox.BackColor.R: pictureBox.BackColor.R; } [Category("Color")] public int Green { set { if (value >= 0 && value < 256) pictureBox.BackColor = Color.FromArgb(pictureBox.BackColor.R, value, pictureBox.BackColor.B); } - get { return pictureBox.BackColor.G; } + get => Inversion ? 255 - pictureBox.BackColor.G: pictureBox.BackColor.G; } [Category("Color")] public int Blue { set { if (value >= 0 && value < 256) pictureBox.BackColor = Color.FromArgb(pictureBox.BackColor.R, pictureBox.BackColor.G, value); } - get { return pictureBox.BackColor.B; } + get => Inversion ? 255 - pictureBox.BackColor.B: pictureBox.BackColor.B; } [Category("Color")] public float RedF { set { if (value >= 0 && value <= 1) pictureBox.BackColor = Color.FromArgb((int)(value * 255), pictureBox.BackColor.G, pictureBox.BackColor.B); } - get { return pictureBox.BackColor.R / 255f; } + get => Inversion ? 1 - pictureBox.BackColor.R / 255f : pictureBox.BackColor.R / 255f; } [Category("Color")] public float GreenF { set { if (value >= 0 && value < 256) pictureBox.BackColor = Color.FromArgb(pictureBox.BackColor.R, (int)(value * 255), pictureBox.BackColor.B); } - get { return pictureBox.BackColor.G / 255f; } + get => Inversion ? 1 - pictureBox.BackColor.G / 255f: pictureBox.BackColor.G / 255f; } [Category("Color")] public float BlueF { set { if (value >= 0 && value < 256) pictureBox.BackColor = Color.FromArgb(pictureBox.BackColor.R, pictureBox.BackColor.G, (int)(value * 255)); } - get { return pictureBox.BackColor.B / 255f; } + get => Inversion ? 1 - pictureBox.BackColor.B / 255f: pictureBox.BackColor.B / 255f; } public ColorControl() diff --git a/Crystallography.Controls/Crystal/BoundControl.cs b/Crystallography.Controls/Crystal/BoundControl.cs index 53109c7..d02d0ce 100644 --- a/Crystallography.Controls/Crystal/BoundControl.cs +++ b/Crystallography.Controls/Crystal/BoundControl.cs @@ -17,7 +17,8 @@ public partial class BoundControl : UserControl public Crystal Crystal { - get => crystal; set + get => crystal; + set { crystal = value; if (crystal != null) @@ -78,9 +79,9 @@ public void SetToInterface(Bound b) #region データベース操作 /// - /// データベースにbondsを追加する + /// データベースにboundsを追加する /// - /// + /// public void Add(Bound bounds) { if (bounds != null && bounds.Index != (0, 0, 0)) @@ -93,7 +94,7 @@ public void Add(Bound bounds) } /// - /// データベースに原子を追加する + /// データベースにboundsを追加する /// /// public void AddRange(IEnumerable bounds) @@ -147,7 +148,13 @@ public void Clear() /// データベース中の全ての境界面を取得 /// /// - public Bound[] GetAll() => table.GetAll(); + public Bound[] GetAll() + { + var bounds = table.GetAll(); + for (int i = 0; i < bounds.Length; i++) + bounds[i].Reset(Crystal); + return bounds; + } #endregion diff --git a/Crystallography.Controls/Crystal/FormScatteringFactor.Designer.cs b/Crystallography.Controls/Crystal/FormScatteringFactor.Designer.cs index c7c19f4..f7269cf 100644 --- a/Crystallography.Controls/Crystal/FormScatteringFactor.Designer.cs +++ b/Crystallography.Controls/Crystal/FormScatteringFactor.Designer.cs @@ -28,7 +28,8 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); + components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormScatteringFactor)); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); @@ -38,370 +39,491 @@ private void InitializeComponent() System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle9 = new System.Windows.Forms.DataGridViewCellStyle(); - this.dataGridView2 = new System.Windows.Forms.DataGridView(); - this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.K = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn7 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn10 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.F = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.dataGridViewTextBoxColumn11 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.RelInt = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.Condition = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.bindingSourceScatteringFactor = new System.Windows.Forms.BindingSource(this.components); - this.dataSet = new Crystallography.Controls.DataSet(); - this.numericUpDownThresholdD = new System.Windows.Forms.NumericUpDown(); - this.label2 = new System.Windows.Forms.Label(); - this.checkBoxHideProhibitedPlanes = new System.Windows.Forms.CheckBox(); - this.checkBoxHideEquivalentPlane = new System.Windows.Forms.CheckBox(); - this.label13 = new System.Windows.Forms.Label(); - this.buttonCopyClipboard = new System.Windows.Forms.Button(); - this.label18 = new System.Windows.Forms.Label(); - this.checkBoxBragBrentano = new System.Windows.Forms.CheckBox(); - this.waveLengthControl1 = new Crystallography.Controls.WaveLengthControl(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); - ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.bindingSourceScatteringFactor)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.dataSet)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.numericUpDownThresholdD)).BeginInit(); - this.SuspendLayout(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle11 = new System.Windows.Forms.DataGridViewCellStyle(); + dataGridView2 = new System.Windows.Forms.DataGridView(); + dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + K = new System.Windows.Forms.DataGridViewTextBoxColumn(); + dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + dataGridViewTextBoxColumn4 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + dataGridViewTextBoxColumn5 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + dataGridViewTextBoxColumn6 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + dataGridViewTextBoxColumn7 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + dataGridViewTextBoxColumn9 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + dataGridViewTextBoxColumn10 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + F = new System.Windows.Forms.DataGridViewTextBoxColumn(); + dataGridViewTextBoxColumn11 = new System.Windows.Forms.DataGridViewTextBoxColumn(); + RelInt = new System.Windows.Forms.DataGridViewTextBoxColumn(); + Condition = new System.Windows.Forms.DataGridViewTextBoxColumn(); + bindingSourceScatteringFactor = new System.Windows.Forms.BindingSource(components); + dataSet = new DataSet(); + numericUpDownThresholdD = new System.Windows.Forms.NumericUpDown(); + label2 = new System.Windows.Forms.Label(); + checkBoxHideProhibitedPlanes = new System.Windows.Forms.CheckBox(); + checkBoxHideEquivalentPlane = new System.Windows.Forms.CheckBox(); + label13 = new System.Windows.Forms.Label(); + buttonCopyClipboard = new System.Windows.Forms.Button(); + label18 = new System.Windows.Forms.Label(); + checkBoxBragBrentano = new System.Windows.Forms.CheckBox(); + waveLengthControl1 = new WaveLengthControl(); + toolTip = new System.Windows.Forms.ToolTip(components); + checkBoxTest = new System.Windows.Forms.CheckBox(); + label1 = new System.Windows.Forms.Label(); + label3 = new System.Windows.Forms.Label(); + label4 = new System.Windows.Forms.Label(); + label5 = new System.Windows.Forms.Label(); + label6 = new System.Windows.Forms.Label(); + label7 = new System.Windows.Forms.Label(); + panel1 = new System.Windows.Forms.Panel(); + numericBoxL_step = new NumericBox(); + numericBoxK_step = new NumericBox(); + numericBoxH_step = new NumericBox(); + numericBoxL_max = new NumericBox(); + numericBoxK_max = new NumericBox(); + numericBoxL_min = new NumericBox(); + numericBoxK_min = new NumericBox(); + numericBoxH_max = new NumericBox(); + numericBoxH_min = new NumericBox(); + ((System.ComponentModel.ISupportInitialize)dataGridView2).BeginInit(); + ((System.ComponentModel.ISupportInitialize)bindingSourceScatteringFactor).BeginInit(); + ((System.ComponentModel.ISupportInitialize)dataSet).BeginInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownThresholdD).BeginInit(); + panel1.SuspendLayout(); + SuspendLayout(); // // dataGridView2 // - this.dataGridView2.AllowUserToAddRows = false; - this.dataGridView2.AllowUserToDeleteRows = false; - this.dataGridView2.AllowUserToResizeRows = false; - dataGridViewCellStyle1.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.dataGridView2.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1; - this.dataGridView2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.dataGridView2.AutoGenerateColumns = false; - this.dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.dataGridView2.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.dataGridViewTextBoxColumn1, - this.K, - this.dataGridViewTextBoxColumn3, - this.dataGridViewTextBoxColumn4, - this.dataGridViewTextBoxColumn5, - this.dataGridViewTextBoxColumn6, - this.dataGridViewTextBoxColumn7, - this.dataGridViewTextBoxColumn9, - this.dataGridViewTextBoxColumn10, - this.F, - this.dataGridViewTextBoxColumn11, - this.RelInt, - this.Condition}); - this.dataGridView2.DataSource = this.bindingSourceScatteringFactor; - this.dataGridView2.Location = new System.Drawing.Point(1, 111); - this.dataGridView2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.dataGridView2.MultiSelect = false; - this.dataGridView2.Name = "dataGridView2"; - this.dataGridView2.ReadOnly = true; - this.dataGridView2.RowHeadersVisible = false; - this.dataGridView2.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing; - this.dataGridView2.RowTemplate.Height = 21; - this.dataGridView2.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; - this.dataGridView2.Size = new System.Drawing.Size(824, 285); - this.dataGridView2.TabIndex = 0; + resources.ApplyResources(dataGridView2, "dataGridView2"); + dataGridView2.AllowUserToAddRows = false; + dataGridView2.AllowUserToDeleteRows = false; + dataGridView2.AllowUserToResizeRows = false; + dataGridViewCellStyle1.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F); + dataGridView2.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1; + dataGridView2.AutoGenerateColumns = false; + dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridView2.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { dataGridViewTextBoxColumn1, K, dataGridViewTextBoxColumn3, dataGridViewTextBoxColumn4, dataGridViewTextBoxColumn5, dataGridViewTextBoxColumn6, dataGridViewTextBoxColumn7, dataGridViewTextBoxColumn9, dataGridViewTextBoxColumn10, F, dataGridViewTextBoxColumn11, RelInt, Condition }); + dataGridView2.DataSource = bindingSourceScatteringFactor; + dataGridView2.MultiSelect = false; + dataGridView2.Name = "dataGridView2"; + dataGridView2.ReadOnly = true; + dataGridView2.RowHeadersVisible = false; + dataGridView2.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing; + dataGridView2.RowTemplate.DefaultCellStyle.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridView2.RowTemplate.DefaultCellStyle.BackColor = System.Drawing.SystemColors.Control; + dataGridView2.RowTemplate.DefaultCellStyle.Font = new System.Drawing.Font("メイリオ", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 128); + dataGridView2.RowTemplate.DefaultCellStyle.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridView2.RowTemplate.DefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridView2.RowTemplate.DefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridView2.RowTemplate.Height = 21; + dataGridView2.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; + toolTip.SetToolTip(dataGridView2, resources.GetString("dataGridView2.ToolTip")); // // dataGridViewTextBoxColumn1 // - this.dataGridViewTextBoxColumn1.DataPropertyName = "H"; - this.dataGridViewTextBoxColumn1.HeaderText = "h"; - this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1"; - this.dataGridViewTextBoxColumn1.ReadOnly = true; - this.dataGridViewTextBoxColumn1.Width = 30; + dataGridViewTextBoxColumn1.DataPropertyName = "H"; + dataGridViewCellStyle2.NullValue = null; + dataGridViewTextBoxColumn1.DefaultCellStyle = dataGridViewCellStyle2; + resources.ApplyResources(dataGridViewTextBoxColumn1, "dataGridViewTextBoxColumn1"); + dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1"; + dataGridViewTextBoxColumn1.ReadOnly = true; // // K // - this.K.DataPropertyName = "K"; - this.K.HeaderText = "k"; - this.K.Name = "K"; - this.K.ReadOnly = true; - this.K.Width = 30; + K.DataPropertyName = "K"; + resources.ApplyResources(K, "K"); + K.Name = "K"; + K.ReadOnly = true; // // dataGridViewTextBoxColumn3 // - this.dataGridViewTextBoxColumn3.DataPropertyName = "L"; - this.dataGridViewTextBoxColumn3.HeaderText = "l"; - this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3"; - this.dataGridViewTextBoxColumn3.ReadOnly = true; - this.dataGridViewTextBoxColumn3.Width = 30; + dataGridViewTextBoxColumn3.DataPropertyName = "L"; + dataGridViewCellStyle3.NullValue = null; + dataGridViewTextBoxColumn3.DefaultCellStyle = dataGridViewCellStyle3; + resources.ApplyResources(dataGridViewTextBoxColumn3, "dataGridViewTextBoxColumn3"); + dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3"; + dataGridViewTextBoxColumn3.ReadOnly = true; // // dataGridViewTextBoxColumn4 // - this.dataGridViewTextBoxColumn4.DataPropertyName = "Multi"; - this.dataGridViewTextBoxColumn4.HeaderText = "Multi."; - this.dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4"; - this.dataGridViewTextBoxColumn4.ReadOnly = true; - this.dataGridViewTextBoxColumn4.Width = 45; + dataGridViewTextBoxColumn4.DataPropertyName = "Multi"; + resources.ApplyResources(dataGridViewTextBoxColumn4, "dataGridViewTextBoxColumn4"); + dataGridViewTextBoxColumn4.Name = "dataGridViewTextBoxColumn4"; + dataGridViewTextBoxColumn4.ReadOnly = true; // // dataGridViewTextBoxColumn5 // - this.dataGridViewTextBoxColumn5.DataPropertyName = "D"; - dataGridViewCellStyle2.Format = "G7"; - dataGridViewCellStyle2.NullValue = null; - this.dataGridViewTextBoxColumn5.DefaultCellStyle = dataGridViewCellStyle2; - this.dataGridViewTextBoxColumn5.HeaderText = "d (Å)"; - this.dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5"; - this.dataGridViewTextBoxColumn5.ReadOnly = true; - this.dataGridViewTextBoxColumn5.Width = 70; + dataGridViewTextBoxColumn5.DataPropertyName = "D"; + dataGridViewCellStyle4.Format = "G7"; + dataGridViewCellStyle4.NullValue = null; + dataGridViewTextBoxColumn5.DefaultCellStyle = dataGridViewCellStyle4; + resources.ApplyResources(dataGridViewTextBoxColumn5, "dataGridViewTextBoxColumn5"); + dataGridViewTextBoxColumn5.Name = "dataGridViewTextBoxColumn5"; + dataGridViewTextBoxColumn5.ReadOnly = true; // // dataGridViewTextBoxColumn6 // - this.dataGridViewTextBoxColumn6.DataPropertyName = "Q"; - dataGridViewCellStyle3.Format = "G7"; - this.dataGridViewTextBoxColumn6.DefaultCellStyle = dataGridViewCellStyle3; - this.dataGridViewTextBoxColumn6.HeaderText = "q (2π/d)"; - this.dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6"; - this.dataGridViewTextBoxColumn6.ReadOnly = true; - this.dataGridViewTextBoxColumn6.Width = 75; + dataGridViewTextBoxColumn6.DataPropertyName = "Q"; + dataGridViewCellStyle5.Format = "G7"; + dataGridViewTextBoxColumn6.DefaultCellStyle = dataGridViewCellStyle5; + resources.ApplyResources(dataGridViewTextBoxColumn6, "dataGridViewTextBoxColumn6"); + dataGridViewTextBoxColumn6.Name = "dataGridViewTextBoxColumn6"; + dataGridViewTextBoxColumn6.ReadOnly = true; // // dataGridViewTextBoxColumn7 // - this.dataGridViewTextBoxColumn7.DataPropertyName = "TwoTheta"; - dataGridViewCellStyle4.Format = "G7"; - this.dataGridViewTextBoxColumn7.DefaultCellStyle = dataGridViewCellStyle4; - this.dataGridViewTextBoxColumn7.HeaderText = "2θ (°)"; - this.dataGridViewTextBoxColumn7.Name = "dataGridViewTextBoxColumn7"; - this.dataGridViewTextBoxColumn7.ReadOnly = true; - this.dataGridViewTextBoxColumn7.Width = 70; + dataGridViewTextBoxColumn7.DataPropertyName = "TwoTheta"; + dataGridViewCellStyle6.Format = "G7"; + dataGridViewTextBoxColumn7.DefaultCellStyle = dataGridViewCellStyle6; + resources.ApplyResources(dataGridViewTextBoxColumn7, "dataGridViewTextBoxColumn7"); + dataGridViewTextBoxColumn7.Name = "dataGridViewTextBoxColumn7"; + dataGridViewTextBoxColumn7.ReadOnly = true; // // dataGridViewTextBoxColumn9 // - this.dataGridViewTextBoxColumn9.DataPropertyName = "F_real"; - dataGridViewCellStyle5.Format = "G7"; - this.dataGridViewTextBoxColumn9.DefaultCellStyle = dataGridViewCellStyle5; - this.dataGridViewTextBoxColumn9.HeaderText = "F_real"; - this.dataGridViewTextBoxColumn9.Name = "dataGridViewTextBoxColumn9"; - this.dataGridViewTextBoxColumn9.ReadOnly = true; - this.dataGridViewTextBoxColumn9.Width = 70; + dataGridViewTextBoxColumn9.DataPropertyName = "F_real"; + dataGridViewCellStyle7.Format = "G7"; + dataGridViewTextBoxColumn9.DefaultCellStyle = dataGridViewCellStyle7; + resources.ApplyResources(dataGridViewTextBoxColumn9, "dataGridViewTextBoxColumn9"); + dataGridViewTextBoxColumn9.Name = "dataGridViewTextBoxColumn9"; + dataGridViewTextBoxColumn9.ReadOnly = true; // // dataGridViewTextBoxColumn10 // - this.dataGridViewTextBoxColumn10.DataPropertyName = "F_inv"; - dataGridViewCellStyle6.Format = "G7"; - this.dataGridViewTextBoxColumn10.DefaultCellStyle = dataGridViewCellStyle6; - this.dataGridViewTextBoxColumn10.HeaderText = "F_inv"; - this.dataGridViewTextBoxColumn10.Name = "dataGridViewTextBoxColumn10"; - this.dataGridViewTextBoxColumn10.ReadOnly = true; - this.dataGridViewTextBoxColumn10.Width = 70; + dataGridViewTextBoxColumn10.DataPropertyName = "F_inv"; + dataGridViewCellStyle8.Format = "G7"; + dataGridViewTextBoxColumn10.DefaultCellStyle = dataGridViewCellStyle8; + resources.ApplyResources(dataGridViewTextBoxColumn10, "dataGridViewTextBoxColumn10"); + dataGridViewTextBoxColumn10.Name = "dataGridViewTextBoxColumn10"; + dataGridViewTextBoxColumn10.ReadOnly = true; // // F // - this.F.DataPropertyName = "F"; - dataGridViewCellStyle7.Format = "G7"; - this.F.DefaultCellStyle = dataGridViewCellStyle7; - this.F.HeaderText = "|F|"; - this.F.Name = "F"; - this.F.ReadOnly = true; - this.F.Width = 70; + F.DataPropertyName = "F"; + dataGridViewCellStyle9.Format = "G7"; + F.DefaultCellStyle = dataGridViewCellStyle9; + resources.ApplyResources(F, "F"); + F.Name = "F"; + F.ReadOnly = true; // // dataGridViewTextBoxColumn11 // - this.dataGridViewTextBoxColumn11.DataPropertyName = "F2"; - dataGridViewCellStyle8.Format = "G7"; - this.dataGridViewTextBoxColumn11.DefaultCellStyle = dataGridViewCellStyle8; - this.dataGridViewTextBoxColumn11.HeaderText = "F^2"; - this.dataGridViewTextBoxColumn11.Name = "dataGridViewTextBoxColumn11"; - this.dataGridViewTextBoxColumn11.ReadOnly = true; - this.dataGridViewTextBoxColumn11.Width = 70; + dataGridViewTextBoxColumn11.DataPropertyName = "F2"; + dataGridViewCellStyle10.Format = "G7"; + dataGridViewTextBoxColumn11.DefaultCellStyle = dataGridViewCellStyle10; + resources.ApplyResources(dataGridViewTextBoxColumn11, "dataGridViewTextBoxColumn11"); + dataGridViewTextBoxColumn11.Name = "dataGridViewTextBoxColumn11"; + dataGridViewTextBoxColumn11.ReadOnly = true; // // RelInt // - this.RelInt.DataPropertyName = "RelInt"; - dataGridViewCellStyle9.Format = "G7"; - this.RelInt.DefaultCellStyle = dataGridViewCellStyle9; - this.RelInt.HeaderText = "Rel. Int. (%)"; - this.RelInt.Name = "RelInt"; - this.RelInt.ReadOnly = true; - this.RelInt.Width = 90; + RelInt.DataPropertyName = "RelInt"; + dataGridViewCellStyle11.Format = "G7"; + RelInt.DefaultCellStyle = dataGridViewCellStyle11; + resources.ApplyResources(RelInt, "RelInt"); + RelInt.Name = "RelInt"; + RelInt.ReadOnly = true; // // Condition // - this.Condition.DataPropertyName = "Condition"; - this.Condition.HeaderText = "Condition"; - this.Condition.Name = "Condition"; - this.Condition.ReadOnly = true; - this.Condition.Width = 80; + Condition.DataPropertyName = "Condition"; + resources.ApplyResources(Condition, "Condition"); + Condition.Name = "Condition"; + Condition.ReadOnly = true; // // bindingSourceScatteringFactor // - this.bindingSourceScatteringFactor.DataMember = "DataTableScatteringFactor"; - this.bindingSourceScatteringFactor.DataSource = this.dataSet; + bindingSourceScatteringFactor.DataMember = "DataTableScatteringFactor"; + bindingSourceScatteringFactor.DataSource = dataSet; // // dataSet // - this.dataSet.DataSetName = "DataSet"; - this.dataSet.Namespace = "http://tempuri.org/DataSet1.xsd"; - this.dataSet.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; + dataSet.DataSetName = "DataSet"; + dataSet.Namespace = "http://tempuri.org/DataSet1.xsd"; + dataSet.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; // // numericUpDownThresholdD // - this.numericUpDownThresholdD.DecimalPlaces = 4; - this.numericUpDownThresholdD.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.numericUpDownThresholdD.Increment = new decimal(new int[] { - 1, - 0, - 0, - 65536}); - this.numericUpDownThresholdD.Location = new System.Drawing.Point(574, 36); - this.numericUpDownThresholdD.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.numericUpDownThresholdD.Maximum = new decimal(new int[] { - 1000, - 0, - 0, - 0}); - this.numericUpDownThresholdD.Minimum = new decimal(new int[] { - 1, - 0, - 0, - 65536}); - this.numericUpDownThresholdD.Name = "numericUpDownThresholdD"; - this.numericUpDownThresholdD.Size = new System.Drawing.Size(61, 25); - this.numericUpDownThresholdD.TabIndex = 5; - this.numericUpDownThresholdD.Value = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.numericUpDownThresholdD.ValueChanged += new System.EventHandler(this.numericUpDownThresholdD_ValueChanged); + resources.ApplyResources(numericUpDownThresholdD, "numericUpDownThresholdD"); + numericUpDownThresholdD.DecimalPlaces = 4; + numericUpDownThresholdD.Increment = new decimal(new int[] { 1, 0, 0, 65536 }); + numericUpDownThresholdD.Maximum = new decimal(new int[] { 1000, 0, 0, 0 }); + numericUpDownThresholdD.Minimum = new decimal(new int[] { 1, 0, 0, 65536 }); + numericUpDownThresholdD.Name = "numericUpDownThresholdD"; + toolTip.SetToolTip(numericUpDownThresholdD, resources.GetString("numericUpDownThresholdD.ToolTip")); + numericUpDownThresholdD.Value = new decimal(new int[] { 1, 0, 0, 0 }); + numericUpDownThresholdD.ValueChanged += numericUpDownThresholdD_ValueChanged; // // label2 // - this.label2.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.label2.Location = new System.Drawing.Point(517, 14); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(171, 20); - this.label2.TabIndex = 6; - this.label2.Text = "Threshold of d-spacing"; + resources.ApplyResources(label2, "label2"); + label2.Name = "label2"; + toolTip.SetToolTip(label2, resources.GetString("label2.ToolTip")); // // checkBoxHideProhibitedPlanes // - this.checkBoxHideProhibitedPlanes.AutoSize = true; - this.checkBoxHideProhibitedPlanes.Checked = true; - this.checkBoxHideProhibitedPlanes.CheckState = System.Windows.Forms.CheckState.Checked; - this.checkBoxHideProhibitedPlanes.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.checkBoxHideProhibitedPlanes.Location = new System.Drawing.Point(305, 78); - this.checkBoxHideProhibitedPlanes.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.checkBoxHideProhibitedPlanes.Name = "checkBoxHideProhibitedPlanes"; - this.checkBoxHideProhibitedPlanes.Size = new System.Drawing.Size(161, 21); - this.checkBoxHideProhibitedPlanes.TabIndex = 8; - this.checkBoxHideProhibitedPlanes.Text = "Hide prohibited planes"; - this.checkBoxHideProhibitedPlanes.CheckedChanged += new System.EventHandler(this.numericUpDownThresholdD_ValueChanged); + resources.ApplyResources(checkBoxHideProhibitedPlanes, "checkBoxHideProhibitedPlanes"); + checkBoxHideProhibitedPlanes.Checked = true; + checkBoxHideProhibitedPlanes.CheckState = System.Windows.Forms.CheckState.Checked; + checkBoxHideProhibitedPlanes.Name = "checkBoxHideProhibitedPlanes"; + toolTip.SetToolTip(checkBoxHideProhibitedPlanes, resources.GetString("checkBoxHideProhibitedPlanes.ToolTip")); + checkBoxHideProhibitedPlanes.CheckedChanged += numericUpDownThresholdD_ValueChanged; // // checkBoxHideEquivalentPlane // - this.checkBoxHideEquivalentPlane.AutoSize = true; - this.checkBoxHideEquivalentPlane.Checked = true; - this.checkBoxHideEquivalentPlane.CheckState = System.Windows.Forms.CheckState.Checked; - this.checkBoxHideEquivalentPlane.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.checkBoxHideEquivalentPlane.Location = new System.Drawing.Point(305, 53); - this.checkBoxHideEquivalentPlane.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.checkBoxHideEquivalentPlane.Name = "checkBoxHideEquivalentPlane"; - this.checkBoxHideEquivalentPlane.Size = new System.Drawing.Size(159, 21); - this.checkBoxHideEquivalentPlane.TabIndex = 8; - this.checkBoxHideEquivalentPlane.Text = "Hide equivalent planes"; - this.checkBoxHideEquivalentPlane.CheckedChanged += new System.EventHandler(this.numericUpDownThresholdD_ValueChanged); + resources.ApplyResources(checkBoxHideEquivalentPlane, "checkBoxHideEquivalentPlane"); + checkBoxHideEquivalentPlane.Checked = true; + checkBoxHideEquivalentPlane.CheckState = System.Windows.Forms.CheckState.Checked; + checkBoxHideEquivalentPlane.Name = "checkBoxHideEquivalentPlane"; + toolTip.SetToolTip(checkBoxHideEquivalentPlane, resources.GetString("checkBoxHideEquivalentPlane.ToolTip")); + checkBoxHideEquivalentPlane.CheckedChanged += numericUpDownThresholdD_ValueChanged; // // label13 // - this.label13.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.label13.Location = new System.Drawing.Point(638, 42); - this.label13.Name = "label13"; - this.label13.Size = new System.Drawing.Size(28, 20); - this.label13.TabIndex = 6; - this.label13.Text = "Å"; + resources.ApplyResources(label13, "label13"); + label13.Name = "label13"; + toolTip.SetToolTip(label13, resources.GetString("label13.ToolTip")); // // buttonCopyClipboard // - this.buttonCopyClipboard.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.buttonCopyClipboard.Location = new System.Drawing.Point(506, 78); - this.buttonCopyClipboard.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.buttonCopyClipboard.Name = "buttonCopyClipboard"; - this.buttonCopyClipboard.Size = new System.Drawing.Size(141, 28); - this.buttonCopyClipboard.TabIndex = 8; - this.buttonCopyClipboard.Text = "Copy to Clipboard"; - this.buttonCopyClipboard.UseVisualStyleBackColor = true; - this.buttonCopyClipboard.Click += new System.EventHandler(this.buttonCopyClipBoard_Click); + resources.ApplyResources(buttonCopyClipboard, "buttonCopyClipboard"); + buttonCopyClipboard.Name = "buttonCopyClipboard"; + toolTip.SetToolTip(buttonCopyClipboard, resources.GetString("buttonCopyClipboard.ToolTip")); + buttonCopyClipboard.UseVisualStyleBackColor = true; + buttonCopyClipboard.Click += buttonCopyClipBoard_Click; // // label18 // - this.label18.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.label18.Location = new System.Drawing.Point(517, 36); - this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(51, 20); - this.label18.TabIndex = 6; - this.label18.Text = "under"; + resources.ApplyResources(label18, "label18"); + label18.Name = "label18"; + toolTip.SetToolTip(label18, resources.GetString("label18.ToolTip")); // // checkBoxBragBrentano // - this.checkBoxBragBrentano.AutoSize = true; - this.checkBoxBragBrentano.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.checkBoxBragBrentano.Location = new System.Drawing.Point(307, 1); - this.checkBoxBragBrentano.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.checkBoxBragBrentano.Name = "checkBoxBragBrentano"; - this.checkBoxBragBrentano.Size = new System.Drawing.Size(199, 38); - this.checkBoxBragBrentano.TabIndex = 8; - this.checkBoxBragBrentano.Text = "Powder diffraction intensities \r\n(Bragg Brentano optics)"; - this.checkBoxBragBrentano.CheckedChanged += new System.EventHandler(this.checkBoxBragBrentano_CheckedChanged); + resources.ApplyResources(checkBoxBragBrentano, "checkBoxBragBrentano"); + checkBoxBragBrentano.Name = "checkBoxBragBrentano"; + toolTip.SetToolTip(checkBoxBragBrentano, resources.GetString("checkBoxBragBrentano.ToolTip")); + checkBoxBragBrentano.CheckedChanged += checkBoxBragBrentano_CheckedChanged; // // waveLengthControl1 // - this.waveLengthControl1.AutoSize = true; - this.waveLengthControl1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.waveLengthControl1.Energy = 8.041147213082D; - this.waveLengthControl1.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.waveLengthControl1.Location = new System.Drawing.Point(10, 2); - this.waveLengthControl1.Margin = new System.Windows.Forms.Padding(0); - this.waveLengthControl1.MinimumSize = new System.Drawing.Size(200, 0); - this.waveLengthControl1.Name = "waveLengthControl1"; - this.waveLengthControl1.ShowWaveSource = true; - this.waveLengthControl1.Size = new System.Drawing.Size(201, 104); - this.waveLengthControl1.TabIndex = 9; - this.waveLengthControl1.TextFont = new System.Drawing.Font("メイリオ", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.waveLengthControl1.WaveLength = 0.1541871066667D; - this.waveLengthControl1.WaveSource = Crystallography.WaveSource.Xray; - this.waveLengthControl1.XrayWaveSourceElementNumber = 29; - this.waveLengthControl1.XrayWaveSourceLine = Crystallography.XrayLine.Ka; - this.waveLengthControl1.WavelengthChanged += new System.EventHandler(this.waveLengthControl1_WavelengthChanged); + resources.ApplyResources(waveLengthControl1, "waveLengthControl1"); + waveLengthControl1.Direction = System.Windows.Forms.FlowDirection.TopDown; + waveLengthControl1.Energy = 8.04114721D; + waveLengthControl1.Monochrome = true; + waveLengthControl1.Name = "waveLengthControl1"; + waveLengthControl1.ShowWaveSource = true; + toolTip.SetToolTip(waveLengthControl1, resources.GetString("waveLengthControl1.ToolTip")); + waveLengthControl1.WaveLength = 0.1541871066667D; + waveLengthControl1.WaveSource = WaveSource.Xray; + waveLengthControl1.XrayWaveSourceElementNumber = 29; + waveLengthControl1.XrayWaveSourceLine = XrayLine.Ka; + waveLengthControl1.WavelengthChanged += waveLengthControl1_WavelengthChanged; + // + // checkBoxTest + // + resources.ApplyResources(checkBoxTest, "checkBoxTest"); + checkBoxTest.Name = "checkBoxTest"; + toolTip.SetToolTip(checkBoxTest, resources.GetString("checkBoxTest.ToolTip")); + checkBoxTest.UseVisualStyleBackColor = true; + checkBoxTest.CheckedChanged += checkBoxTest_CheckedChanged; + // + // label1 + // + resources.ApplyResources(label1, "label1"); + label1.Name = "label1"; + toolTip.SetToolTip(label1, resources.GetString("label1.ToolTip")); + // + // label3 + // + resources.ApplyResources(label3, "label3"); + label3.Name = "label3"; + toolTip.SetToolTip(label3, resources.GetString("label3.ToolTip")); + // + // label4 + // + resources.ApplyResources(label4, "label4"); + label4.Name = "label4"; + toolTip.SetToolTip(label4, resources.GetString("label4.ToolTip")); + // + // label5 + // + resources.ApplyResources(label5, "label5"); + label5.Name = "label5"; + toolTip.SetToolTip(label5, resources.GetString("label5.ToolTip")); + // + // label6 + // + resources.ApplyResources(label6, "label6"); + label6.Name = "label6"; + toolTip.SetToolTip(label6, resources.GetString("label6.ToolTip")); + // + // label7 + // + resources.ApplyResources(label7, "label7"); + label7.Name = "label7"; + toolTip.SetToolTip(label7, resources.GetString("label7.ToolTip")); + // + // panel1 + // + resources.ApplyResources(panel1, "panel1"); + panel1.Controls.Add(numericBoxL_step); + panel1.Controls.Add(numericBoxK_step); + panel1.Controls.Add(numericBoxH_step); + panel1.Controls.Add(numericBoxL_max); + panel1.Controls.Add(numericBoxK_max); + panel1.Controls.Add(numericBoxL_min); + panel1.Controls.Add(numericBoxK_min); + panel1.Controls.Add(numericBoxH_max); + panel1.Controls.Add(numericBoxH_min); + panel1.Controls.Add(label1); + panel1.Controls.Add(label5); + panel1.Controls.Add(label6); + panel1.Controls.Add(label4); + panel1.Controls.Add(label7); + panel1.Controls.Add(label3); + panel1.Name = "panel1"; + toolTip.SetToolTip(panel1, resources.GetString("panel1.ToolTip")); + // + // numericBoxL_step + // + resources.ApplyResources(numericBoxL_step, "numericBoxL_step"); + numericBoxL_step.BackColor = System.Drawing.Color.Transparent; + numericBoxL_step.DecimalPlaces = 3; + numericBoxL_step.Maximum = 1D; + numericBoxL_step.Minimum = 0.001D; + numericBoxL_step.Name = "numericBoxL_step"; + numericBoxL_step.RadianValue = 0.00017453292519943296D; + numericBoxL_step.RoundErrorAccuracy = -1; + numericBoxL_step.ShowUpDown = true; + numericBoxL_step.SmartIncrement = true; + toolTip.SetToolTip(numericBoxL_step, resources.GetString("numericBoxL_step.ToolTip")); + numericBoxL_step.Value = 0.01D; + numericBoxL_step.ValueChanged += numericBoxH_min_ValueChanged; + // + // numericBoxK_step + // + resources.ApplyResources(numericBoxK_step, "numericBoxK_step"); + numericBoxK_step.BackColor = System.Drawing.Color.Transparent; + numericBoxK_step.DecimalPlaces = 3; + numericBoxK_step.Maximum = 1D; + numericBoxK_step.Minimum = 0.001D; + numericBoxK_step.Name = "numericBoxK_step"; + numericBoxK_step.RadianValue = 0.00017453292519943296D; + numericBoxK_step.RoundErrorAccuracy = -1; + numericBoxK_step.ShowUpDown = true; + numericBoxK_step.SmartIncrement = true; + toolTip.SetToolTip(numericBoxK_step, resources.GetString("numericBoxK_step.ToolTip")); + numericBoxK_step.Value = 0.01D; + numericBoxK_step.ValueChanged += numericBoxH_min_ValueChanged; + // + // numericBoxH_step + // + resources.ApplyResources(numericBoxH_step, "numericBoxH_step"); + numericBoxH_step.BackColor = System.Drawing.Color.Transparent; + numericBoxH_step.DecimalPlaces = 3; + numericBoxH_step.Maximum = 1D; + numericBoxH_step.Minimum = 0.001D; + numericBoxH_step.Name = "numericBoxH_step"; + numericBoxH_step.RadianValue = 0.00017453292519943296D; + numericBoxH_step.RoundErrorAccuracy = -1; + numericBoxH_step.ShowUpDown = true; + numericBoxH_step.SmartIncrement = true; + toolTip.SetToolTip(numericBoxH_step, resources.GetString("numericBoxH_step.ToolTip")); + numericBoxH_step.Value = 0.01D; + numericBoxH_step.ValueChanged += numericBoxH_min_ValueChanged; + // + // numericBoxL_max + // + resources.ApplyResources(numericBoxL_max, "numericBoxL_max"); + numericBoxL_max.BackColor = System.Drawing.Color.Transparent; + numericBoxL_max.Name = "numericBoxL_max"; + numericBoxL_max.RadianValue = 0.017453292519943295D; + numericBoxL_max.RoundErrorAccuracy = -1; + numericBoxL_max.ShowUpDown = true; + toolTip.SetToolTip(numericBoxL_max, resources.GetString("numericBoxL_max.ToolTip")); + numericBoxL_max.Value = 1D; + numericBoxL_max.ValueChanged += numericBoxH_min_ValueChanged; + // + // numericBoxK_max + // + resources.ApplyResources(numericBoxK_max, "numericBoxK_max"); + numericBoxK_max.BackColor = System.Drawing.Color.Transparent; + numericBoxK_max.Name = "numericBoxK_max"; + numericBoxK_max.RoundErrorAccuracy = -1; + numericBoxK_max.ShowUpDown = true; + toolTip.SetToolTip(numericBoxK_max, resources.GetString("numericBoxK_max.ToolTip")); + numericBoxK_max.ValueChanged += numericBoxH_min_ValueChanged; + // + // numericBoxL_min + // + resources.ApplyResources(numericBoxL_min, "numericBoxL_min"); + numericBoxL_min.BackColor = System.Drawing.Color.Transparent; + numericBoxL_min.Name = "numericBoxL_min"; + numericBoxL_min.RoundErrorAccuracy = -1; + numericBoxL_min.ShowUpDown = true; + toolTip.SetToolTip(numericBoxL_min, resources.GetString("numericBoxL_min.ToolTip")); + numericBoxL_min.ValueChanged += numericBoxH_min_ValueChanged; + // + // numericBoxK_min + // + resources.ApplyResources(numericBoxK_min, "numericBoxK_min"); + numericBoxK_min.BackColor = System.Drawing.Color.Transparent; + numericBoxK_min.Name = "numericBoxK_min"; + numericBoxK_min.RoundErrorAccuracy = -1; + numericBoxK_min.ShowUpDown = true; + toolTip.SetToolTip(numericBoxK_min, resources.GetString("numericBoxK_min.ToolTip")); + numericBoxK_min.ValueChanged += numericBoxH_min_ValueChanged; + // + // numericBoxH_max + // + resources.ApplyResources(numericBoxH_max, "numericBoxH_max"); + numericBoxH_max.BackColor = System.Drawing.Color.Transparent; + numericBoxH_max.Name = "numericBoxH_max"; + numericBoxH_max.RoundErrorAccuracy = -1; + numericBoxH_max.ShowUpDown = true; + toolTip.SetToolTip(numericBoxH_max, resources.GetString("numericBoxH_max.ToolTip")); + numericBoxH_max.ValueChanged += numericBoxH_min_ValueChanged; + // + // numericBoxH_min + // + resources.ApplyResources(numericBoxH_min, "numericBoxH_min"); + numericBoxH_min.BackColor = System.Drawing.Color.Transparent; + numericBoxH_min.Name = "numericBoxH_min"; + numericBoxH_min.RoundErrorAccuracy = -1; + numericBoxH_min.ShowUpDown = true; + toolTip.SetToolTip(numericBoxH_min, resources.GetString("numericBoxH_min.ToolTip")); + numericBoxH_min.ValueChanged += numericBoxH_min_ValueChanged; // // FormScatteringFactor // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(831, 398); - this.Controls.Add(this.waveLengthControl1); - this.Controls.Add(this.buttonCopyClipboard); - this.Controls.Add(this.dataGridView2); - this.Controls.Add(this.label2); - this.Controls.Add(this.label18); - this.Controls.Add(this.numericUpDownThresholdD); - this.Controls.Add(this.label13); - this.Controls.Add(this.checkBoxHideProhibitedPlanes); - this.Controls.Add(this.checkBoxBragBrentano); - this.Controls.Add(this.checkBoxHideEquivalentPlane); - this.Font = new System.Drawing.Font("Segoe UI Symbol", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); - this.Name = "FormScatteringFactor"; - this.ShowIcon = false; - this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; - this.Text = "Scattering Factor"; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormCrystallographicInformation_FormClosing); - this.Load += new System.EventHandler(this.FormCrystallographicInformation_Load); - this.VisibleChanged += new System.EventHandler(this.FormScatteringFactor_VisibleChanged); - ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.bindingSourceScatteringFactor)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.dataSet)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.numericUpDownThresholdD)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - + resources.ApplyResources(this, "$this"); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + Controls.Add(checkBoxTest); + Controls.Add(waveLengthControl1); + Controls.Add(buttonCopyClipboard); + Controls.Add(dataGridView2); + Controls.Add(label2); + Controls.Add(label18); + Controls.Add(numericUpDownThresholdD); + Controls.Add(label13); + Controls.Add(checkBoxHideProhibitedPlanes); + Controls.Add(checkBoxBragBrentano); + Controls.Add(checkBoxHideEquivalentPlane); + Controls.Add(panel1); + Name = "FormScatteringFactor"; + ShowIcon = false; + toolTip.SetToolTip(this, resources.GetString("$this.ToolTip")); + FormClosing += FormCrystallographicInformation_FormClosing; + Load += FormCrystallographicInformation_Load; + VisibleChanged += FormScatteringFactor_VisibleChanged; + ((System.ComponentModel.ISupportInitialize)dataGridView2).EndInit(); + ((System.ComponentModel.ISupportInitialize)bindingSourceScatteringFactor).EndInit(); + ((System.ComponentModel.ISupportInitialize)dataSet).EndInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownThresholdD).EndInit(); + panel1.ResumeLayout(false); + panel1.PerformLayout(); + ResumeLayout(false); + PerformLayout(); } #endregion @@ -418,6 +540,24 @@ private void InitializeComponent() private System.Windows.Forms.BindingSource bindingSourceScatteringFactor; private WaveLengthControl waveLengthControl1; private DataSet dataSet; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.CheckBox checkBoxTest; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Panel panel1; + private NumericBox numericBoxH_min; + private NumericBox numericBoxL_step; + private NumericBox numericBoxK_step; + private NumericBox numericBoxH_step; + private NumericBox numericBoxL_max; + private NumericBox numericBoxK_max; + private NumericBox numericBoxL_min; + private NumericBox numericBoxK_min; + private NumericBox numericBoxH_max; private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1; private System.Windows.Forms.DataGridViewTextBoxColumn K; private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3; @@ -431,6 +571,5 @@ private void InitializeComponent() private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn11; private System.Windows.Forms.DataGridViewTextBoxColumn RelInt; private System.Windows.Forms.DataGridViewTextBoxColumn Condition; - private System.Windows.Forms.ToolTip toolTip; } } \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/FormScatteringFactor.cs b/Crystallography.Controls/Crystal/FormScatteringFactor.cs index 4cec0f3..86751b6 100644 --- a/Crystallography.Controls/Crystal/FormScatteringFactor.cs +++ b/Crystallography.Controls/Crystal/FormScatteringFactor.cs @@ -1,8 +1,10 @@ +using MathNet.Numerics; using System; using System.Linq; using System.Reflection; using System.Text; using System.Windows.Forms; +using static IronPython.Modules._ast; namespace Crystallography.Controls { @@ -97,9 +99,15 @@ private void waveLengthControl1_WavelengthChanged(object sender, EventArgs e) private void SetSortedPlanes() { + if (checkBoxTest.Checked) + { + numericBoxH_min_ValueChanged(new object(), new EventArgs()); + return; + } + var c = (Crystal)Crystal.Clone(); - c.SetVectorOfG((double)numericUpDownThresholdD.Value / 10, waveLengthControl1.WaveSource, false); + c.SetVectorOfG((double)numericUpDownThresholdD.Value / 10, waveLengthControl1.WaveSource); Array.Sort(c.VectorOfG, (g1, g2) => g2.d.CompareTo(g1.d)); @@ -166,6 +174,7 @@ private void SetSortedPlanes() } } } + dataGridView2.DefaultCellStyle.Format = ""; dataGridView2.VirtualMode = true; bindingSourceScatteringFactor.DataMember = dataMember; @@ -174,9 +183,48 @@ private void SetSortedPlanes() //dataGridView2.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells; } + /// + /// eXgR[h + /// + /// + /// + private void numericBoxH_min_ValueChanged(object sender, EventArgs e) + { + var c = (Crystal)Crystal.Clone(); + //UbindingSource + var dataMember = bindingSourceScatteringFactor.DataMember; + dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; + dataGridView2.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None; + bindingSourceScatteringFactor.DataMember = ""; + dataSet.DataTableScatteringFactor.Clear(); + for (int i = 0; i < dataGridView2.Columns.Count; i++) + this.dataGridView2.Columns[i].Visible = true; + for (double h = numericBoxH_min.Value; h <= numericBoxH_max.Value + 1e-10; h += numericBoxH_step.Value) + for (double k = numericBoxK_min.Value; k <= numericBoxK_max.Value + 1e-10; k += numericBoxK_step.Value) + for (double l = numericBoxL_min.Value; l <= numericBoxL_max.Value + 1e-10; l += numericBoxL_step.Value) + { + var gLength = (h * c.A_Star + k * c.B_Star + l * c.C_Star).Length; + var d = 1 / gLength; + var twoTheta = 2 * Math.Asin(gLength * waveLengthControl1.WaveLength / 2) / Math.PI * 180; + var F = Crystal.GetStructureFactor(waveLengthControl1.WaveSource, c.Atoms, (h, k, l), 1 / d / d / 4.0); + dataSet.DataTableScatteringFactor.Add(h, k, l, 1, d, twoTheta, F, F.MagnitudeSquared(), []); + } + dataGridView2.DefaultCellStyle.Format = "g8"; + dataGridView2.VirtualMode = true; + bindingSourceScatteringFactor.DataMember = dataMember; + } + + private void checkBoxTest_CheckedChanged(object sender, EventArgs e) + { + panel1.Visible=checkBoxTest.Checked; + if (panel1.Visible) + numericBoxH_min_ValueChanged(sender, e); + else + SetSortedPlanes(); + } } } \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/FormScatteringFactor.ja.resx b/Crystallography.Controls/Crystal/FormScatteringFactor.ja.resx new file mode 100644 index 0000000..b4f2d9b --- /dev/null +++ b/Crystallography.Controls/Crystal/FormScatteringFactor.ja.resx @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + メイリオ, 9.75pt + + + 69, 20 + + + d値の上限 + + + メイリオ, 9.75pt + + + 145, 24 + + + 消滅する面は非表示 + + + メイリオ, 9.75pt + + + 132, 24 + + + 等価な面は非表示 + + + + True + + + メイリオ, 9.75pt + + + 162, 30 + + + クリップボードにコピー + + + メイリオ, 9.75pt + + + 175, 24 + + + 粉末回折(BB光学系)強度 + + + 52, 24 + + + メイリオ, 9.75pt + + + 散乱因子 + + \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/FormScatteringFactor.resx b/Crystallography.Controls/Crystal/FormScatteringFactor.resx index 8b928d6..210b72b 100644 --- a/Crystallography.Controls/Crystal/FormScatteringFactor.resx +++ b/Crystallography.Controls/Crystal/FormScatteringFactor.resx @@ -1,4 +1,64 @@ + + @@ -57,28 +117,1239 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + 6 + + + True - - + + + + 239, 53 + + + panel1 + + + $this + + + 11 + + + + + + 3 + + + 2 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 80, 69 + + + True + + + checkBoxTest + + + 9 + + + d (Å) + + + |F| + + + + 0, 0, 0, 0 + + + Scattering Factor + + + $this + + + panel1 + + + test + + + waveLengthControl1 + + + 4 + + + 1000, 28 + + + F + + + 1000, 28 + + + 1, 18 + + + True + + + 14, 17 + + + 13 + + + + + + 238, 1 + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 7 + + + System.Windows.Forms.BindingSource, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 10, 2 + + + l + + + Segoe UI Symbol, 9pt + + + Segoe UI Symbol, 9.75pt + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 30 + + + Segoe UI Symbol, 9pt + + + 6 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 440, 78 + + + 80 + + + Arial, 9pt + + + 3, 4, 3, 4 + + + 48, 21 + + + 3 + + + 2 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 199, 38 + + + Segoe UI Symbol, 9.75pt + + + Segoe UI Symbol, 9pt + + + h + + + + + + numericUpDownThresholdD + + + 6 + + + Hide prohibited planes + + + 10 + + + 7 + + + True + + + Segoe UI Symbol, 9.75pt + + + Segoe UI Symbol, 9.75pt + + + $this + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 824, 284 + + + + + + Microsoft Sans Serif, 9pt + + + 1000, 28 + + + 161, 21 + + + panel1 + + + Segoe UI Symbol, 9pt + + + panel1 + + + checkBoxHideEquivalentPlane + + + dataGridViewTextBoxColumn3 + + + q (2π/d) + + + dataGridViewTextBoxColumn5 + + + Segoe UI Symbol, 9.75pt + + + 8 + + + K + + + Segoe UI Symbol, 9pt + + + 600, 2 + + + 8 + + + 4 + + + 1, 18 + + + 61, 25 + + + h + + + + + + + + + 6 + + + 70 + + + 5 + + + Segoe UI Symbol, 9pt + + + Segoe UI Symbol, 9pt + + + Segoe UI Symbol, 9pt + + + Segoe UI Symbol, 9pt + + + Segoe UI Symbol, 9.75pt + + + label5 + + + System.Windows.Forms.DataGridView, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + 40, 24 + + + 617, 8 + + + 487, 38 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Segoe UI Symbol, 9pt + + + 6 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 29, 69 + + + toolTip + + + + + + Crystallography.Controls.DataSet, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 68, 24 + + + 3, 4, 3, 4 + + + 0, 0, 0, 0 + + + $this + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + 567, 40 + + + 1, 18 + + + panel1 + + + Crystallography.Controls.WaveLengthControl, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 34, 17 + + + System.Windows.Forms.ToolTip, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Copy to Clipboard + + + 500, 500 + + + Hide equivalent planes + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + numericBoxK_min + + + 7 + + + 7 + + + True + + + System.Windows.Forms.Button, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + k + + + Min + + + 0, 0, 0, 0 + + + + + + 3, 4, 3, 4 + + + Segoe UI Symbol, 9.75pt + + + dataGridView2 + + + + + + dataGridViewTextBoxColumn1 + + + panel1 + + + label3 + + + 7 + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + < + + + 30, 0 + + + Segoe UI Symbol, 9.75pt + + + 3, 4, 3, 4 + + + panel1 + + + 5 + + + 28, 20 + + + Segoe UI Symbol, 9.75pt + + + $this + + + 1000, 28 + + + 0, 0, 0, 0 + + + 80, 20 + + + panel1 + + + 70 + + + dataGridViewTextBoxColumn10 + + + numericBoxH_min + + + + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 202, 97 + + + Max + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 8 + + + System.Windows.Forms.Panel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + label2 + + + 6 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + + + + System.Windows.Forms.Form, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + buttonCopyClipboard + + + 200, 0 + + + 9, 72 + + + 1000, 28 + + + 70 + + + 40, 24 + + + Segoe UI Symbol, 9.75pt + + + + + + F_real + + + Segoe UI Symbol, 9.75pt + + + 29, 45 + + + 1 + + + 0, 0, 0, 0 + + + Segoe UI Symbol, 9pt + + + 0 + + + panel1 + + + 1, 18 + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + 6 + + + Segoe UI Symbol, 9.75pt + + + Segoe UI Symbol, 9.75pt + + + Segoe UI Symbol, 9pt + + + 141, 28 + + + + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + panel1 + + + 1 + + + Threshold of d-spacing + + + 505, 36 + + + + + + numericBoxK_max + + + Segoe UI Symbol, 9.75pt + + + 70 + + + label18 + + + label6 + + + l + + + Segoe UI Symbol, 9.75pt + + + Multi. + + + 9, 47 + + + 7 + + + 2θ (°) + + + 131, 45 + + + 1000, 28 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 6 + + + 3, 110 + + + Segoe UI Symbol, 9pt + + + F^2 + + + 5 + + + 3, 4, 3, 4 + + + checkBoxHideProhibitedPlanes + + + Condition + + + Step + + + 33, 17 + + + dataSet + + + Segoe UI Symbol, 9.75pt + + + Segoe UI Symbol, 9.75pt + + + + + + $this + + + panel1 + + + 40, 24 + + + + + + 1000, 28 + + + panel1 + + + True + + + 144, 17 + + + RelInt + + + Segoe UI Symbol, 9pt + + + 30 + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1, 18 + + + Segoe UI Symbol, 9.75pt + + + 831, 398 + + + Segoe UI Symbol, 9pt + + + 159, 21 + + + Segoe UI Symbol, 9.75pt + + + Segoe UI Symbol, 9.75pt + + + + + True + + + + Manual + + + 239, 78 + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 80, 0 + + + Segoe UI Symbol, 9pt + + + 6 + + + numericBoxL_step + + + 75 + + + 9 + + + $this + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 6 + + + + + + 7 + + + 10 + + + + + + panel1 + + + panel1 + + + FormScatteringFactor + + + Segoe UI Symbol, 9pt + + + 129, 0 + + + True + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 7 + + + 70 + + + 30 + + + True + + + panel1 + + + Segoe UI Symbol, 9pt + + + Segoe UI Symbol, 9.75pt + + + True + + + Top, Bottom, Left, Right + + + 96, 96 + + + label13 + + + 29, 20 + + + True + + + 3, 4, 3, 4 + + + 1000, 28 + + + 68, 24 + + + dataGridViewTextBoxColumn7 + + + 1, 18 + + + 0 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + checkBoxBragBrentano + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 9 + + + 0, 0, 0, 0 + + + True + + + False + + + dataGridViewTextBoxColumn9 + + + Segoe UI Symbol, 9pt + + + 0, 0, 0, 0 + + + Powder diffraction intensities +(Bragg Brentano optics) + + + 9, 22 + + + label1 + + + numericBoxK_step + + + Segoe UI Symbol, 9pt + + + numericBoxH_step + + + 17, 20 + + + 1, 18 + + + 90 + + + 0, 0, 0, 0 + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + numericBoxH_max + + + dataGridViewTextBoxColumn4 + + + 3, 4, 3, 4 + + + 80, 45 + + + 40, 24 + + + + + + + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 40, 24 + + + 40, 24 + + + Segoe UI Symbol, 9pt + + + 11 + + + 6 + + + Segoe UI Symbol, 9.75pt + + + + + + + + + GrowAndShrink + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.DataGridViewTextBoxColumn, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 15, 17 + + + 440, 14 + + + 0, 0, 0, 0 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + label4 + + + 0, 0, 0, 0 + + + $this + + + Condition + + + 1000, 28 + + + 45 + + + Segoe UI Symbol, 9pt + + + 68, 24 + + + panel1 + + + + + + 131, 20 + + + 10 + + + 8 + + + 14 + + + Segoe UI Symbol, 9pt + + + $this + + + F_inv + + + numericBoxL_min + + + k + + + 200, 97 + + + Segoe UI Symbol, 9.75pt + + + dataGridViewTextBoxColumn11 + + + 12 + + + 8 + + + 1, 18 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 12 + + + 7 + + + + + + 1, 18 + + + dataGridViewTextBoxColumn6 + + + bindingSourceScatteringFactor + + + Segoe UI Symbol, 9pt + + + 30, 17 + + + 131, 69 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Segoe UI Symbol, 9pt + + + $this + + + 7 + + + Segoe UI Symbol, 9.75pt + + + Segoe UI Symbol, 9pt + + + 70 + + + Rel. Int. (%) + + + 0 + + + 11, 17 + + + 8 + + + label7 + + + 7 + + + numericBoxL_max + + + Segoe UI Symbol, 9pt + + + 85 + + + 351, 17 True - + + ja + + True 115, 17 - - 351, 17 + + True + + + True 444, 17 - - 85 + + True \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/PoleFigureControl2.Designer.cs b/Crystallography.Controls/Crystal/PoleFigureControl2.Designer.cs new file mode 100644 index 0000000..32b4c3b --- /dev/null +++ b/Crystallography.Controls/Crystal/PoleFigureControl2.Designer.cs @@ -0,0 +1,159 @@ +namespace Crystallography.Controls +{ + partial class PoleFigureControl2 + { + /// + /// 必要なデザイナー変数です。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 使用中のリソースをすべてクリーンアップします。 + /// + /// マネージ リソースが破棄される場合 true、破棄されない場合は false です。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region コンポーネント デザイナーで生成されたコード + + /// + /// デザイナー サポートに必要なメソッドです。このメソッドの内容を + /// コード エディターで変更しないでください。 + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PoleFigureControl2)); + flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + pictureBox = new System.Windows.Forms.PictureBox(); + pictureBox1 = new System.Windows.Forms.PictureBox(); + numericBoxResolution = new NumericBox(); + label9 = new System.Windows.Forms.Label(); + comboBoxColor = new System.Windows.Forms.ComboBox(); + numericBoxMax = new NumericBox(); + numericBoxMin = new NumericBox(); + label1 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)pictureBox).BeginInit(); + ((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit(); + SuspendLayout(); + // + // flowLayoutPanel1 + // + resources.ApplyResources(flowLayoutPanel1, "flowLayoutPanel1"); + flowLayoutPanel1.Name = "flowLayoutPanel1"; + // + // pictureBox + // + resources.ApplyResources(pictureBox, "pictureBox"); + pictureBox.Name = "pictureBox"; + pictureBox.TabStop = false; + pictureBox.DoubleClick += pictureBox_DoubleClick; + // + // pictureBox1 + // + resources.ApplyResources(pictureBox1, "pictureBox1"); + pictureBox1.Name = "pictureBox1"; + pictureBox1.TabStop = false; + // + // numericBoxResolution + // + resources.ApplyResources(numericBoxResolution, "numericBoxResolution"); + numericBoxResolution.BackColor = System.Drawing.Color.Transparent; + numericBoxResolution.Maximum = 30D; + numericBoxResolution.Minimum = 1D; + numericBoxResolution.Name = "numericBoxResolution"; + numericBoxResolution.RadianValue = 0.10471975511965977D; + numericBoxResolution.RoundErrorAccuracy = -1; + numericBoxResolution.ShowUpDown = true; + numericBoxResolution.SmartIncrement = true; + numericBoxResolution.Value = 6D; + numericBoxResolution.ValueChanged += numericUpDownResolution_Click; + // + // label9 + // + resources.ApplyResources(label9, "label9"); + label9.Name = "label9"; + // + // comboBoxColor + // + resources.ApplyResources(comboBoxColor, "comboBoxColor"); + comboBoxColor.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + comboBoxColor.FormattingEnabled = true; + comboBoxColor.Items.AddRange(new object[] { resources.GetString("comboBoxColor.Items"), resources.GetString("comboBoxColor.Items1") }); + comboBoxColor.Name = "comboBoxColor"; + comboBoxColor.SelectedIndexChanged += Combobox_SelectedIndexChanged; + // + // numericBoxMax + // + resources.ApplyResources(numericBoxMax, "numericBoxMax"); + numericBoxMax.BackColor = System.Drawing.Color.Transparent; + numericBoxMax.Maximum = 1000000D; + numericBoxMax.Minimum = 0D; + numericBoxMax.Name = "numericBoxMax"; + numericBoxMax.RadianValue = 1.7453292519943295D; + numericBoxMax.RoundErrorAccuracy = -1; + numericBoxMax.ShowTrigonomeric = true; + numericBoxMax.ShowUpDown = true; + numericBoxMax.SmartIncrement = true; + numericBoxMax.Value = 100D; + numericBoxMax.ValueChanged += numericBoxMax_ValueChanged; + // + // numericBoxMin + // + resources.ApplyResources(numericBoxMin, "numericBoxMin"); + numericBoxMin.BackColor = System.Drawing.Color.Transparent; + numericBoxMin.Maximum = 10000D; + numericBoxMin.Minimum = 0D; + numericBoxMin.Name = "numericBoxMin"; + numericBoxMin.RoundErrorAccuracy = -1; + numericBoxMin.ShowTrigonomeric = true; + numericBoxMin.ShowUpDown = true; + numericBoxMin.SmartIncrement = true; + numericBoxMin.ValueChanged += numericBoxMax_ValueChanged; + // + // label1 + // + resources.ApplyResources(label1, "label1"); + label1.BackColor = System.Drawing.Color.White; + label1.Name = "label1"; + // + // PoleFigureControl2 + // + resources.ApplyResources(this, "$this"); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + Controls.Add(label1); + Controls.Add(numericBoxResolution); + Controls.Add(numericBoxMin); + Controls.Add(label9); + Controls.Add(comboBoxColor); + Controls.Add(numericBoxMax); + Controls.Add(pictureBox1); + Controls.Add(flowLayoutPanel1); + Controls.Add(pictureBox); + Name = "PoleFigureControl2"; + Load += PoleFigureControl_Load; + ((System.ComponentModel.ISupportInitialize)pictureBox).EndInit(); + ((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label9; + public System.Windows.Forms.ComboBox comboBoxColor; + private NumericBox numericBoxMin; + private NumericBox numericBoxMax; + private NumericBox numericBoxResolution; + private System.Windows.Forms.Label label1; + } +} diff --git a/Crystallography.Controls/Crystal/PoleFigureControl2.cs b/Crystallography.Controls/Crystal/PoleFigureControl2.cs new file mode 100644 index 0000000..d1a42c9 --- /dev/null +++ b/Crystallography.Controls/Crystal/PoleFigureControl2.cs @@ -0,0 +1,361 @@ +using System; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using V3 = OpenTK.Vector3d; +using V4 = OpenTK.Vector4d; + +namespace Crystallography.Controls; + +public partial class PoleFigureControl2 : UserControl +{ + /// + /// Histogram:方位ベクトルの頻度, Average: 方位ベクトルが持つ値の平均値, Sigma: 方位ベクトルが持つ値の標準偏差 + /// + public enum DrawingModeEnum { Histogram, Average, Sigma } + + public DrawingModeEnum DrawingMode = DrawingModeEnum.Histogram; + + private StereonetProjectionMode stereonetProjectionMode = StereonetProjectionMode.Schmidt; + private StereonetDirection stereonetDirecion = StereonetDirection.Equrtor; + private bool showOneDeg = false; + private bool showTenDeg = true; + + private Color backGroundColor = Color.White; + private Color OneDegColor = Color.FromArgb(192, 192, 255); + private Color TenDegColor = Color.FromArgb(128, 128, 255); + private Color NinetyDegColor = Color.FromArgb(0, 0, 255); + + private V4[] vectors = null; + /// + /// + /// + public V4[] Vectors + { + get => vectors; + set + { + if (value != null) + { + vectors = value; + GeneratePixels(); + Draw(); + } + } + } + + private double[][] Pixels = null; + + private double magnification = 1; + private PointD center = new(0, 0); + + //記号や線など + public (PointD Point, double Radius, Color Color, bool Fill, string Text)[] Circles = null; + public (PointD[] Point, double LineWidth, Color Color)[] Lines = null; + + + public PoleFigureControl2() + { + InitializeComponent(); + comboBoxColor.SelectedIndex = 0; + } + + private void PoleFigureControl_Load(object sender, EventArgs e) + { + magnification = Math.Min(pictureBox.Width, pictureBox.Height) / 2.4; + center = new PointD(0, 0); + } + + public void Draw() + { + magnification = Math.Min(pictureBox.Width, pictureBox.Height) / 2.4; + if (pictureBox.ClientSize.Width != 0 && pictureBox.ClientSize.Height != 0) + { + Bitmap bmp = new Bitmap(pictureBox.ClientSize.Width, pictureBox.ClientSize.Height); + Graphics g = Graphics.FromImage(bmp); + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + g.Transform = new System.Drawing.Drawing2D.Matrix((float)magnification, 0, 0, (float)magnification, + (float)(pictureBox.ClientSize.Width / 2.0 - center.X * magnification), (float)(pictureBox.ClientSize.Height / 2.0 - center.Y * magnification)); + + g.Clear(Color.White); + DrawDensity(g, Pixels); + DrawOutline(g); + DrawSymbols(g); + DrawColorScale(); + pictureBox.Image = bmp; + } + } + + private void pictureBox_DoubleClick(object sender, EventArgs e) + { + if (Pixels == null) return; + float mag = 480; + Bitmap bmp = new(1024, 1024); + Graphics g = Graphics.FromImage(bmp); + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + g.Transform = new System.Drawing.Drawing2D.Matrix(mag, 0, 0, mag, 512, 512); + g.Clear(Color.White); + DrawDensity(g, Pixels); + DrawOutline(g); + DrawSymbols(g); + Clipboard.SetDataObject(bmp); + } + + /// + /// Vectors[]から、Pixels[][]を生成 + /// + private void GeneratePixels() + { + if (vectors == null) return; + + //まず、指定された解像度でpixelsを生成 + var div1 = (int)(90.0 / numericBoxResolution.Value);//放射方向の分割数 + Pixels = new double[div1][]; + var areas = new double[div1]; + for (int i = 0; i < div1; i++) + { + var circumference_length = 2 * Math.PI * (i + 0.5) / div1;//Pixels[i]の円周の長さ (外側と内側の平均) + var div2 = Math.Max(3, (int)(circumference_length * div1)); + Pixels[i] = new double[div2]; + areas[i] = Math.PI * (2 * i + 1) / div1 / div1 / div2; + } + + //ベクトルからPixelのインデックスを計算するファンクション + var f = new Func(v => + { + v.Normalize(); + // vが単位ベクトルの時、 (v.X / Sqrt(1 + v.Z), v.Y / Sqrt(1 + v.Z) )が シュミットネット上の点 + var (x, y) = (v.X / Math.Sqrt(1 + v.Z), v.Y / Math.Sqrt(1 + v.Z)); + var i = (int)(Math.Sqrt(x * x + y * y) * div1); + i = Math.Min(Math.Max(i, 0), div1 - 1); + var j = (int)((Math.Atan2(y, x) + Math.PI) / 2 / Math.PI * Pixels[i].Length); + j = Math.Min(Math.Max(j, 0), Pixels[i].Length - 1); + return (i, j); + }); + + if (DrawingMode == DrawingModeEnum.Histogram) + { + foreach (var v in vectors.Select(v => new V3(v.X, v.Y, v.Z)).Where(v => v.Z >= 0)) + { + var (i, j) = f(v); + Pixels[i][j] += 1 / areas[i]; + } + } + else if (DrawingMode == DrawingModeEnum.Average) + { + var count = new int[Pixels.Length][]; + for (int i = 0; i < count.Length; i++) + count[i] = new int[Pixels[i].Length]; + + foreach (var v in vectors.Where(v => v.Z >= 0)) + { + var (i, j) = f(new(v.X, v.Y, v.Z)); + Pixels[i][j] += v.W; + count[i][j]++; + } + for (int i = 0; i < div1; i++) + for (int j = 0; j < Pixels[i].Length; j++) + if (count[i][j]!=0) + Pixels[i][j] /= count[i][j]; + } + else + { + var tmp = new List [Pixels.Length][]; + for (int i = 0; i < tmp.Length; i++) + { + tmp[i] = new List[Pixels[i].Length]; + for (int j = 0; j < tmp[i].Length; j++) + tmp[i][j] = []; + } + + foreach (var v in vectors.Where(v => v.Z >= 0)) + { + var (i, j) = f(new(v.X, v.Y, v.Z)); + tmp[i][j].Add(v.W); + } + for (int i = 0; i < div1; i++) + for (int j = 0; j < Pixels[i].Length; j++) + if (tmp[i][j].Count > 1) + Pixels[i][j] = Statistics.Deviation([.. tmp[i][j]]); + } + + var max = Pixels.Max(e => e.Max()); + var log10 = Math.Floor(Math.Log10(max)); + max = (int)(max / Math.Pow(10, log10 - 3) + 0.5) * Math.Pow(10, log10 - 3); + numericBoxMax.Value = max; + + var min = Pixels.Min(e => e.Min()); + if(min>0) + { + log10 = Math.Floor(Math.Log10(min)); + min = (int)(min / Math.Pow(10, log10 - 3) - 0.5) * Math.Pow(10, log10 - 3); + } + numericBoxMin.Value = min; + + + } + + public void DrawDensity(Graphics g, double[][] pixels) + { + if (pixels == null) return; + var max = pixels.Max(e => e.Max()); + var min = pixels.Min(e => e.Min()); + label1.Text = "Max: " + max.ToString("g5") + "; Min: " + min.ToString("g5"); + + var scale = comboBoxColor.SelectedIndex == 0 ? PseudoBitmap.ColorScaleColdWarmLiner : PseudoBitmap.ColorScaleGrayLiner; + + for (int i = pixels.Length - 1; i >= 0; i--) + for (int j = 0; j < pixels[i].Length; j++) + { + var val = (pixels[i][j] - numericBoxMin.Value) / (numericBoxMax.Value - numericBoxMin.Value); + + int density = Math.Min(65535, Math.Max((int)(val * 65535), 0)); + + g.FillPie(new SolidBrush(Color.FromArgb(scale[density].R, scale[density].G, scale[density].B)), + -(i + 1.0) / pixels.Length, -(i + 1.0) / pixels.Length, (i + 1.0) / pixels.Length * 2, (i + 1.0) / pixels.Length * 2, + -(double)j / pixels[i].Length * 360.0, 1.0 / pixels[i].Length * 360.0); + } + } + + #region DrawOutline 輪郭を描画する) + + public void DrawOutline(Graphics g) + { + if (stereonetDirecion == StereonetDirection.Equrtor)//赤道モードのとき + { + + int div = 1000; + PointD[] pt1 = new PointD[div]; + PointD[] pt2 = new PointD[div]; + + double[] cos2 = new double[div]; + double[] sin2 = new double[div]; + + for (int i = 0; i < div; i++) + { + double d = (double)i / div * Math.PI - Math.PI / 2; + cos2[i] = Math.Cos(d); + sin2[i] = Math.Sin(d); + } + + for (int w = 1; w < 90; w++) + if (showOneDeg || w % 10 == 0) + { + Pen pen = w % 10 == 0 ? new Pen(new SolidBrush(TenDegColor), 0.002f) : new Pen(new SolidBrush(OneDegColor), 0.0005f); + pen.LineJoin = System.Drawing.Drawing2D.LineJoin.Round; + double theta = w * Math.PI / 180.0, cos1 = Math.Cos(theta), sin1 = Math.Sin(theta); + for (int i = 0; i < div; i++) + { + pt1[i] = 1 / Math.Sqrt(1 + cos2[i] * sin1) * new PointD(sin2[i] * sin1, cos1); + pt2[i] = -pt1[i]; + } + g.DrawLines(pen, pt1); + g.DrawLines(pen, pt2); + } + + for (int i = 0; i < div; i++) + { + double d = (double)i / div * Math.PI; + cos2[i] = Math.Cos(d); + sin2[i] = Math.Sin(d); + } + + for (int w = 1; w < 90; w++) + if (showOneDeg || w % 10 == 0) + { + Pen pen = w % 10 == 0 ? new Pen(new SolidBrush(TenDegColor), 0.002f) : new Pen(new SolidBrush(OneDegColor), 0.0005f); + pen.LineJoin = System.Drawing.Drawing2D.LineJoin.Round; + double theta = w * Math.PI / 180.0, cos1 = Math.Cos(theta), sin1 = Math.Sin(theta); + for (int i = 0; i < div; i++) + { + pt1[i] = 1 / Math.Sqrt(1 + cos1 * sin2[i]) * new PointD(sin1 * sin2[i], cos2[i]); + pt2[i] = -pt1[i]; + } + g.DrawLines(pen, pt1); + g.DrawLines(pen, pt2); + } + } + else//極モードのとき + { + + for (int w = 1; w < 180; w++) + if (showOneDeg || w % 10 == 0) + { + Pen pen = w % 10 == 0 ? new Pen(new SolidBrush(TenDegColor), 0.002f) : new Pen(new SolidBrush(OneDegColor), 0.0005f); + double theta = w * Math.PI / 180.0; + g.DrawLine(pen, -Math.Cos(theta), -Math.Sin(theta), Math.Cos(theta), Math.Sin(theta)); + if (w < 90) + { + double radius = Math.Sin(Math.PI / 4 - theta / 2) * Math.Sqrt(2); + g.DrawArc(pen, -radius, -radius, 2 * radius, 2 * radius, 0, 2 * Math.PI); + } + } + } + g.DrawArc(new Pen(new SolidBrush(NinetyDegColor), 0.004f), -1, -1, 2, 2, 0, 360); + g.DrawLine(new Pen(new SolidBrush(NinetyDegColor), 0.004f), 0f, -1f, 0f, 1f); + g.DrawLine(new Pen(new SolidBrush(NinetyDegColor), 0.004f), -1f, 0f, 1f, 0f); + } + + #endregion DrawOutline 輪郭を描画する) + + public void DrawSymbols(Graphics g) + { + if (Circles != null) + foreach (var s in Circles.Where(s => s.Point.Length2 <= 1)) + { + var p = new PointD(s.Point.X, s.Point.Y); + if (s.Fill) + g.FillCircle(s.Color, p, s.Radius, 255); + else + g.DrawCircle(s.Color, p, s.Radius); + if (s.Text != "") + g.DrawString(s.Text, new Font("Tahoma", 0.08f), new SolidBrush(s.Color), p.ToPointF()); + } + if (Lines != null) + foreach (var l in Lines) + g.DrawLines(new Pen(l.Color, (float)(l.LineWidth / magnification)), l.Point.Select(e => new PointD(e.X, e.Y)).ToArray()); + } + + + public void DrawColorScale() + { + //横 320 縦 35で描画 + Bitmap bmp = new(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height); + Graphics gScale = Graphics.FromImage(bmp); + gScale.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; + + var scale = comboBoxColor.SelectedIndex == 0 ? PseudoBitmap.ColorScaleColdWarmLiner : PseudoBitmap.ColorScaleGrayLiner; + int scaleWidth = 280, scaleHeight = 15, leftMargin = 20, barLength = 5; + for (int i = 0; i < scaleWidth; i++) + { + int dens = (int)(65536.0 * i / scaleWidth); + gScale.DrawLine(new Pen(Color.FromArgb(scale[dens].R, scale[dens].G, scale[dens].B)), new Point(leftMargin + i, 0), new Point(leftMargin + i, scaleHeight)); + } + + for (int i = 0; i < 5; i++) + { + var x = i / 4f * scaleWidth; + var val = (numericBoxMax.Value - numericBoxMin.Value) * i / 4.0 + numericBoxMin.Value; + gScale.DrawLine(new Pen(Color.Black), new PointF(leftMargin + x, scaleHeight), new PointF(leftMargin + x, scaleHeight + barLength)); + gScale.DrawStringWithAlignment($"{val:g6}", new Font("Tahoma", 8f), Color.Black, + new PointD(leftMargin + x, scaleHeight + barLength), new Size(100, 20) + , HorizontalAlignment.Center, System.Windows.Forms.VisualStyles.VerticalAlignment.Top); + } + pictureBox1.Image = bmp; + } + + public object lockObject = new(); + + private void numericUpDownResolution_Click(object sender, EventArgs e) + { + GeneratePixels(); + Draw(); + } + private void Combobox_SelectedIndexChanged(object sender, EventArgs e) => Draw(); + + private void numericBoxMax_ValueChanged(object sender, EventArgs e) => Draw(); + + +} \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/PoleFigureControl2.ja.resx b/Crystallography.Controls/Crystal/PoleFigureControl2.ja.resx new file mode 100644 index 0000000..e552bac --- /dev/null +++ b/Crystallography.Controls/Crystal/PoleFigureControl2.ja.resx @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + メイリオ, 9pt + + + 解像度 + + + 152, 385 + + + 126, 26 + + + メイリオ, 9pt + + + 152, 361 + + + 20, 18 + + + + + + 205, 358 + + + 117, 23 + + + メイリオ, 9pt + + + 最大 + + + 2, 385 + + + 1000, 30 + + + 1, 20 + + + 131, 26 + + + メイリオ, 9pt + + + 最小 + + + 2, 359 + + + 1000, 30 + + + 1, 20 + + + 131, 26 + + + 2, 2 + + + 142, 13 + + + Min: ##.##, Max ####.## + + + Segoe UI Symbol, 9pt + + \ No newline at end of file diff --git a/Crystallography.Controls/Crystal/PoleFigureControl2.resx b/Crystallography.Controls/Crystal/PoleFigureControl2.resx new file mode 100644 index 0000000..15b5a2f --- /dev/null +++ b/Crystallography.Controls/Crystal/PoleFigureControl2.resx @@ -0,0 +1,442 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Segoe UI Symbol, 9.75pt + + + numericBoxMax + + + + 54 + + + 136, -1 + + + 38, 13 + + + numericBoxResolution + + + System.Windows.Forms.FlowLayoutPanel, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1 + + + 10, 20 + + + 42, 19 + + + 42 + + + $this + + + 208, 358 + + + pictureBox + + + comboBoxColor + + + pictureBox1 + + + + 4, 4, 4, 4 + + + 5 + + + 3, 2 + + + Gray scale + + + 10, 20 + + + Color + + + 59 + + + Segoe UI Symbol, 9.75pt + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + $this + + + 4, 4, 4, 4 + + + Resolution + + + 123, 26 + + + 127, 26 + + + 1000, 100 + + + PoleFigureControl2 + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + Min + + + 2, 320 + + + 166, 361 + + + label1 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Segoe UI Symbol, 10pt + + + flowLayoutPanel1 + + + Segoe UI Symbol, 9.75pt + + + + GrowAndShrink + + + Top, Bottom, Left, Right + + + 0 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 127, 26 + + + $this + + + 180, 386 + + + label1 + + + $this + + + 6 + + + 96, 96 + + + True + + + 8 + + + 0, 0 + + + 0, 0, 0, 0 + + + label9 + + + Cold-Warm scale + + + 8, 359 + + + True + + + Max + + + Segoe UI Symbol, 8pt + + + 59 + + + ° + + + 324, 416 + + + 2, 2, 0, 0 + + + 3 + + + 10, 20 + + + 0, 0, 0, 0 + + + 7 + + + 320, 320 + + + 54 + + + 1000, 100 + + + 0, 0, 0, 0 + + + 2 + + + $this + + + Segoe UI Symbol, 9pt + + + 4 + + + NoControl + + + 1000, 100 + + + 114, 23 + + + System.Windows.Forms.UserControl, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 320, 35 + + + 53 + + + $this + + + 8, 386 + + + numericBoxMin + + + 2, 2 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 60 + + + $this + + + $this + + + 59 + + + $this + + + Crystallography.Controls.NumericBox, Crystallography.Controls, Culture=neutral, PublicKeyToken=null + + + 4, 4, 4, 4 + + + 0, 0, 0, 0 + + + 4, 4, 4, 4 + + + Segoe UI Symbol, 9.75pt + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 40 + + + Bottom, Left, Right + + + True + + + ja + + \ No newline at end of file diff --git a/Crystallography.Controls/Crystallography.Controls.csproj b/Crystallography.Controls/Crystallography.Controls.csproj index e0520bc..f9e52f4 100644 --- a/Crystallography.Controls/Crystallography.Controls.csproj +++ b/Crystallography.Controls/Crystallography.Controls.csproj @@ -2,24 +2,33 @@ Library - net8.0-windows10.0.22621.0 + net8.0-windows10.0.26100.0 true - 2024.7.4.1116 - 2024.7.4.1116 + 2024.10.4.0923 + 2024.10.4.0923 PerMonitorV2 true true 7.0 + AnyCPU;x64 true + + true + + true + + true + + diff --git a/Crystallography.Controls/DataSet.Designer.cs b/Crystallography.Controls/DataSet.Designer.cs index f026aa7..9504dfa 100644 --- a/Crystallography.Controls/DataSet.Designer.cs +++ b/Crystallography.Controls/DataSet.Designer.cs @@ -712,11 +712,11 @@ internal void InitVars() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "16.0.0.0")] private void InitClass() { - this.columnH = new global::System.Data.DataColumn("H", typeof(int), null, global::System.Data.MappingType.Element); + this.columnH = new global::System.Data.DataColumn("H", typeof(double), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnH); - this.columnK = new global::System.Data.DataColumn("K", typeof(int), null, global::System.Data.MappingType.Element); + this.columnK = new global::System.Data.DataColumn("K", typeof(double), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnK); - this.columnL = new global::System.Data.DataColumn("L", typeof(int), null, global::System.Data.MappingType.Element); + this.columnL = new global::System.Data.DataColumn("L", typeof(double), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnL); this.columnMulti = new global::System.Data.DataColumn("Multi", typeof(int), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnMulti); diff --git a/Crystallography.Controls/DataSet.cs b/Crystallography.Controls/DataSet.cs index 13fa5e4..67d9526 100644 --- a/Crystallography.Controls/DataSet.cs +++ b/Crystallography.Controls/DataSet.cs @@ -188,6 +188,31 @@ public void Add(int h, int k, int l, int mult, double d, double twoTheta, Comple this.Rows.Add(dr); } + public void Add(double h, double k, double l, int mult, double d, double twoTheta, Complex f, double relInt, string[] condition) + { + DataRow dr = this.NewDataTableScatteringFactorRow(); + dr[this.HColumn] = h; + dr[this.KColumn] = k; + dr[this.LColumn] = l; + dr[this.MultiColumn] = mult; + dr[this.DColumn] = d; + dr[this.QColumn] = Math.PI * 2 / d; + dr[this.TwoThetaColumn] = twoTheta; + dr[this.F_realColumn] = Math.Abs(f.Real) > 1E-18 ? f.Real : 0; + dr[this.F_invColumn] = Math.Abs(f.Imaginary) > 10E-18 ? f.Imaginary : 0; + dr[this.FColumn] = f.Magnitude > 1E-18 ? f.Magnitude : 0; + dr[this.F2Column] = f.Magnitude * f.Magnitude > 1E-18 ? f.Magnitude * f.Magnitude : 0; + dr[RelIntColumn] = relInt * 100 > 1E-18 ? relInt * 100 : 0; + + var str = new System.Text.StringBuilder(); + for (int m = 0; m < condition.Length; m++) + str.Append(m == 0 ? condition[m] : " & " + condition[m]); + + dr[columnCondition] = str.ToString(); + + this.Rows.Add(dr); + } + public new void Clear() => Rows.Clear(); } diff --git a/Crystallography.Controls/DataSet.xsd b/Crystallography.Controls/DataSet.xsd index bfd8882..6fec7e8 100644 --- a/Crystallography.Controls/DataSet.xsd +++ b/Crystallography.Controls/DataSet.xsd @@ -12,104 +12,104 @@ - + - - - - - - - - - - - - - + + + + + + + + + + + + + - + - - - - - - - - - - - + + + + + + + + + + + - + - - - - - - - - + + + + + + + + - + - - - - - - - - - + + + + + + + + + - + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/Crystallography.Controls/Numeric/NumericBox.cs b/Crystallography.Controls/Numeric/NumericBox.cs index 0b37600..5e0ce8a 100644 --- a/Crystallography.Controls/Numeric/NumericBox.cs +++ b/Crystallography.Controls/Numeric/NumericBox.cs @@ -45,6 +45,7 @@ public partial class NumericBox : UserControl } } + [DefaultValue(-1)] /// /// ۂߌ덷ĂƂ(Ⴆ7.11̂͂Ȃ̂ 7.110000000000001ƂA6.011̂͂Ȃ̂6.010999999999999Ƃ) /// ̌덷ĕ\ diff --git a/Crystallography.Controls/Wave/WaveLengthControl.cs b/Crystallography.Controls/Wave/WaveLengthControl.cs index c149357..47fdf74 100644 --- a/Crystallography.Controls/Wave/WaveLengthControl.cs +++ b/Crystallography.Controls/Wave/WaveLengthControl.cs @@ -33,6 +33,9 @@ public partial class WaveLengthControl : UserControl } } + /// + /// コントロールの配置をLeftToRightか、TopDownにするか + /// public FlowDirection Direction { set @@ -62,15 +65,21 @@ public FlowDirection Direction } public FlowDirection direction = FlowDirection.TopDown; + + bool monochrome = true; + /// + /// 単色モードかどうか falseの場合は白色モード + /// public bool Monochrome { set { - numericBoxEnergy.Visible = numericBoxWaveLength.Visible = value; - flowLayoutPanelElement.Visible = WaveSource == WaveSource.Xray && value; - labelFlatWhite.Visible = !value; + monochrome = value; + numericBoxEnergy.Visible = numericBoxWaveLength.Visible = monochrome; + flowLayoutPanelElement.Visible = WaveSource == WaveSource.Xray && monochrome; + labelFlatWhite.Visible = !monochrome; } - get => numericBoxEnergy.Visible; + get => monochrome; } [Localizable(true)] @@ -88,7 +97,6 @@ public Font TextFont } public bool showWaveSource = true; - /// /// WaveSourceを表示するかどうか /// @@ -141,6 +149,7 @@ public double WaveLength get => numericBoxWaveLength.Value / 10.0; } + WaveSource waveSource = WaveSource.Xray; /// /// 線源を取得/設定 /// @@ -148,16 +157,16 @@ public WaveSource WaveSource { set { - if (value == WaveSource.Xray) + waveSource = value; + if (waveSource == WaveSource.Xray) radioButtonXray.Checked = true; - else if (value == WaveSource.Electron) + else if (waveSource == WaveSource.Electron) radioButtonElectron.Checked = true; - else if (value == WaveSource.Neutron) + else radioButtonNeutron.Checked = true; } get { - if (radioButtonXray.Checked) return WaveSource.Xray; else if (radioButtonElectron.Checked) diff --git a/Crystallography/BetheMethod.cs b/Crystallography/BetheMethod.cs index 368addc..e834174 100644 --- a/Crystallography/BetheMethod.cs +++ b/Crystallography/BetheMethod.cs @@ -47,6 +47,9 @@ public class BetheMethod #region フィールド、プロパティ + /// + /// 加速電圧 単位はkV + /// private double AccVoltage { get; set; } private Crystal Crystal { get; } /// @@ -83,7 +86,7 @@ public enum Solver { Eigen_MKL, Eigen_Eigen, MtxExp_MKL, MtxExp_Eigen, Auto } public bool IsBusy => bwCBED == null || bwCBED.IsBusy; /// - /// CBEDのディスク情報 Disks[Z_index][G_index] + /// CBEDのディスク情報 Disks[Z(thickness)_index][G_index], EBSDのときは [Voltage][Z(thickness)_index] /// [XmlIgnore] public CBED_Disk[][] Disks { get; set; } @@ -93,8 +96,13 @@ public enum Solver { Eigen_MKL, Eigen_Eigen, MtxExp_MKL, MtxExp_Eigen, Auto } [NonSerialized] private readonly BackgroundWorker bwCBED = new(); - public event ProgressChangedEventHandler CbedProgressChanged; - public event RunWorkerCompletedEventHandler CbedCompleted; + public event ProgressChangedEventHandler CBED_ProgressChanged; + public event RunWorkerCompletedEventHandler CBED_Completed; + + [NonSerialized] + private readonly BackgroundWorker bwEBSD = new(); + public event ProgressChangedEventHandler EBSD_ProgressChanged; + public event RunWorkerCompletedEventHandler EBSD_Completed; [NonSerialized] private readonly BackgroundWorker bwSTEM = new(); @@ -143,6 +151,15 @@ public BetheMethod(Crystal crystal) bwCBED.ProgressChanged += Cbed_ProgressChanged; bwCBED.DoWork += cbed_DoWork; + bwEBSD = new BackgroundWorker + { + WorkerSupportsCancellation = true, + WorkerReportsProgress = true + }; + bwEBSD.RunWorkerCompleted += Ebsd_RunWorkerCompleted; + bwEBSD.ProgressChanged += Ebsd_ProgressChanged; + bwEBSD.DoWork += ebsd_DoWork; + bwSTEM = new BackgroundWorker { WorkerSupportsCancellation = true, @@ -155,9 +172,9 @@ public BetheMethod(Crystal crystal) #endregion #region CBED - private void Cbed_ProgressChanged(object sender, ProgressChangedEventArgs e) => CbedProgressChanged?.Invoke(sender, e); + private void Cbed_ProgressChanged(object sender, ProgressChangedEventArgs e) => CBED_ProgressChanged?.Invoke(sender, e); - private void Cbed_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) => CbedCompleted?.Invoke(sender, e); + private void Cbed_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) => CBED_Completed?.Invoke(sender, e); public void CancelCBED() { @@ -178,12 +195,10 @@ public void RunCBED(int maxNumOfBloch, double voltage, Matrix3D rotation, { MaxNumOfBloch = maxNumOfBloch; AccVoltage = voltage; - //Wavelength = UniversalConstants.Convert.EnergyToElectronWaveLength(voltage); BaseRotation = new Matrix3D(rotation); BeamDirections = beamDirections; Thicknesses = thickness; - //var cuda = Control.TryUseNativeCUDA(); bwCBED.RunWorkerAsync((LACBED, solver, thread)); } @@ -220,6 +235,13 @@ private unsafe void cbed_DoWork(object sender, DoWorkEventArgs e) //進捗状況報告用の各種定数を初期化 int count = 0; + int progressStep = Beams.Length switch + { + < 100 => 400, + < 200 => 200, + < 300 => 50, + _ => 5 + }; #region solver, thread の設定 if (solver == Solver.Auto || (!EigenEnabled && (solver == Solver.Eigen_Eigen || solver == Solver.MtxExp_Eigen))) @@ -235,6 +257,8 @@ private unsafe void cbed_DoWork(object sender, DoWorkEventArgs e) int bLen = Beams.Length, tLen = Thicknesses.Length; var beamDirectionsP = beamDirectionsValid.AsParallel().WithDegreeOfParallelism(thread); + + //ここからdiskValid[t*tLen +g]を計算. var diskAmplitudeValid = beamDirectionsP.Select(beamDirection => { @@ -299,8 +323,10 @@ private unsafe void cbed_DoWork(object sender, DoWorkEventArgs e) for (int t = 0; t < tLen; t++) for (int b = 0; b < bLen; b++) result[t * bLen + b] *= Exp(PiI * (beams[b].P - 2 * kvac * Surface.Z) * Thicknesses[t]); - Interlocked.Increment(ref count); - if (count % 10 == 0) bwCBED.ReportProgress(count, reportString);//進捗状況を報告 + + if (Interlocked.Increment(ref count) % progressStep == 0) + bwCBED.ReportProgress(count, reportString);//進捗状況を報告 + return result; } finally { Shared.Return(eigenMatrix); ArrayPool.Shared.Return(beams); } @@ -410,169 +436,199 @@ private unsafe void cbed_DoWork(object sender, DoWorkEventArgs e) #endregion #region EBSD + private void Ebsd_ProgressChanged(object sender, ProgressChangedEventArgs e) => EBSD_ProgressChanged?.Invoke(sender, e); + + private void Ebsd_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) => EBSD_Completed?.Invoke(sender, e); + + public void CancelEBSD() + { + if (bwEBSD.IsBusy) + bwEBSD.CancelAsync(); + } + + /// + /// + /// + /// + /// 加速電圧(kV) + /// 基準となる方位 + /// 厚みの配列 + /// 基準となる方位に乗算する方位配列 + public void RunEBSD(int maxNumOfBloch, double[] voltages, Matrix3D rotation, double[] thickness, Vector3DBase[] beamDirections, Solver solver = Solver.Auto, int thread = 1) + { + MaxNumOfBloch = maxNumOfBloch; + + BaseRotation = new Matrix3D(rotation); + BeamDirections = beamDirections; + Thicknesses = thickness; + + bwEBSD.RunWorkerAsync((solver, thread, voltages)); + } + /// /// EBSD計算用 /// /// /// - private void cbed_DoWork2(object sender, DoWorkEventArgs e) + private void ebsd_DoWork(object sender, DoWorkEventArgs e) { - var (solver, thread, cs) = ((Solver, int, double))e.Argument; + var (solver, thread, voltages) = ((Solver, int, double[]))e.Argument; - //波数を計算 - var kvac = UniversalConstants.Convert.EnergyToElectronWaveNumber(AccVoltage); - //U0を計算 - var u0 = getU(AccVoltage).Real.Real; + Disks = new CBED_Disk[voltages.Length][]; + int count = 0; + + var beamDirectionsP = BeamDirections.AsParallel().WithDegreeOfParallelism(thread); int width = (int)Math.Sqrt(BeamDirections.Length); double radius = width / 2.0; bool inside(int i) => (i % width - radius + 0.5) * (i % width - radius + 0.5) + (i / width - radius + 0.5) * (i / width - radius + 0.5) <= radius * radius; - //var beamRotationsValid = BeamRotations.Where((rot, i) => inside(i)).ToList(); - //RotationArrayValidLength = beamRotationsValid.Count; - gDic.Clear(); - //進捗状況報告用の各種定数を初期化 - int count = 0; - - #region solver, thread の設定 - if (solver == Solver.Auto || (!EigenEnabled && (solver == Solver.Eigen_Eigen || solver == Solver.MtxExp_Eigen))) + for (int vIndex = 0; vIndex < voltages.Length; vIndex++) { - if (EigenEnabled) - (solver, thread) = (Solver.MtxExp_Eigen, ProcessorCount); - else - (solver, thread) = (Solver.Eigen_MKL, MklEnabled ? Math.Max(1, ProcessorCount / 4) : ProcessorCount); - } - var reportString = $"{solver}{thread}"; - #endregion + AccVoltage = voltages[vIndex]; + //波数を計算 + var kvac = UniversalConstants.Convert.EnergyToElectronWaveNumber(AccVoltage); + //U0を計算 + var u0 = getU(AccVoltage).Real.Real; + gDic.Clear(); + //進捗状況報告用の各種定数を初期化 - var beamDirectionsP = BeamDirections.AsParallel().WithDegreeOfParallelism(thread); + #region solver, thread の設定 + if (solver == Solver.Auto || (!EigenEnabled && (solver == Solver.Eigen_Eigen || solver == Solver.MtxExp_Eigen))) + { + if (EigenEnabled) + (solver, thread) = (Solver.MtxExp_Eigen, ProcessorCount); + else + (solver, thread) = (Solver.Eigen_MKL, MklEnabled ? Math.Max(1, ProcessorCount / 4) : ProcessorCount); + } + var reportString = $"{solver}{thread}"; + #endregion - //diskAmplitude[r][t][g] - var diskAmplitude = beamDirectionsP.Select((beamDirection, i) => - { - if (!inside(i)) return (null, null); + //diskAmplitude[r][t][g] + var diskAmplitude = beamDirectionsP.Select((beamDirection, i) => + { + if (!inside(i)) return (null, null); - if (bwCBED.CancellationPending) return (null, null); - //var rotZ = beamDirection * zNorm; - //var coeff = 1.0 / rotZ.Z; // = 1/cosTau - var coeff = Math.Abs(1.0 / beamDirection.Z); // = 1/cosTau + if (bwEBSD.CancellationPending) return (null, null); + var coeff = Math.Abs(1.0 / beamDirection.Z); // = 1/cosTau - var vecK0 = getVecK0(kvac, u0, beamDirection); + var vecK0 = getVecK0(kvac, u0, beamDirection); - var beams = Find_gVectors(BaseRotation, vecK0, MaxNumOfBloch, true); - var potentialMatrix = getEigenMatrix(beams); - var len = beams.Length; - //入射面での波動関数を定義 - var psi0 = new DVec(Enumerable.Range(0, len).ToList().Select(g => g == 0 ? One : 0).ToArray()); - - Complex[] result; - - //ポテンシャル行列の固有値、固有ベクトルを取得し、resultに格納 - #region 各ソルバーによる計算 - //Eigen_Eigenの場合 - if (solver == Solver.Eigen_Eigen && EigenEnabled) - result = NativeWrapper.CBEDSolver_Eigen(potentialMatrix, [.. psi0], Thicknesses); - //Eigen_MKL あるいは Eigen_Managedの場合 - else if (solver == Solver.Eigen_MKL) - { - var evd = new DMat(len, len, potentialMatrix).Evd(Symmetricity.Asymmetric); - var alpha = evd.EigenVectors.LU().Solve(psi0); - var resultMat = new DMat(len, Thicknesses.Length); - for (int t = 0; t < Thicknesses.Length; t++) + //var beams = Find_gVectors(BaseRotation, vecK0, MaxNumOfBloch, true); + var beams = Find_gVectors(BaseRotation, vecK0, MaxNumOfBloch); + var potentialMatrix = getEigenMatrix(beams); + var len = beams.Length; + //入射面での波動関数を定義 + var psi0 = new DVec(Enumerable.Range(0, len).ToList().Select(g => g == 0 ? One : 0).ToArray()); + + Complex[] result; + + //ポテンシャル行列の固有値、固有ベクトルを取得し、resultに格納 + #region 各ソルバーによる計算 + //Eigen_Eigenの場合 + if (solver == Solver.Eigen_Eigen && EigenEnabled) + result = NativeWrapper.CBEDSolver_Eigen(potentialMatrix, [.. psi0], Thicknesses); + //Eigen_MKL あるいは Eigen_Managedの場合 + else if (solver == Solver.Eigen_MKL) { - //ガンマの対称行列×アルファを作成 - var gammmaAlpha = new DVec(evd.EigenValues.Select((ev, i) => Exp(TwoPiI * ev * t * coeff) * alpha[i]).ToArray()); - //深さtにおけるψを求める - resultMat.SetColumn(t, evd.EigenVectors.Multiply(gammmaAlpha)); + var evd = new DMat(len, len, potentialMatrix).Evd(Symmetricity.Asymmetric); + var alpha = evd.EigenVectors.LU().Solve(psi0); + var resultMat = new DMat(len, Thicknesses.Length); + for (int t = 0; t < Thicknesses.Length; t++) + { + //ガンマの対称行列×アルファを作成 + var gammmaAlpha = new DVec(evd.EigenValues.Select((ev, i) => Exp(TwoPiI * ev * t * coeff) * alpha[i]).ToArray()); + //深さtにおけるψを求める + resultMat.SetColumn(t, evd.EigenVectors.Multiply(gammmaAlpha)); + } + result = resultMat.Values; } - result = resultMat.Values; - } - //MtxExp_Eigenの場合 - else if (solver == Solver.MtxExp_Eigen && EigenEnabled) - result = NativeWrapper.CBEDSolver_MatExp(potentialMatrix, [.. psi0], Thicknesses); - //MtxExp_MKLの場合 - else - { - var resultMat = new DMat(len, Thicknesses.Length); - var matExp = (DMat)(TwoPiI * coeff * Thicknesses[0] * new DMat(len, len, potentialMatrix)).Exponential(); - var vec = matExp.Multiply(psi0); - resultMat.SetColumn(0, vec); - - if (Thicknesses.Length > 1) + //MtxExp_Eigenの場合 + else if (solver == Solver.MtxExp_Eigen && EigenEnabled) + result = NativeWrapper.CBEDSolver_MatExp(potentialMatrix, [.. psi0], Thicknesses); + //MtxExp_MKLの場合 + else { - if (Thicknesses[1] - Thicknesses[0] == Thicknesses[0]) - matExp = (DMat)(TwoPiI * coeff * (Thicknesses[1] - Thicknesses[0]) * new DMat(len, len, potentialMatrix)).Exponential(); - for (int t = 1; t < Thicknesses.Length; t++) + var resultMat = new DMat(len, Thicknesses.Length); + var matExp = (DMat)(TwoPiI * coeff * Thicknesses[0] * new DMat(len, len, potentialMatrix)).Exponential(); + var vec = matExp.Multiply(psi0); + resultMat.SetColumn(0, vec); + + if (Thicknesses.Length > 1) { - vec = (DVec)matExp.Multiply(vec); - resultMat.SetColumn(t, vec); + if (Thicknesses[1] - Thicknesses[0] == Thicknesses[0]) + matExp = (DMat)(TwoPiI * coeff * (Thicknesses[1] - Thicknesses[0]) * new DMat(len, len, potentialMatrix)).Exponential(); + for (int t = 1; t < Thicknesses.Length; t++) + { + vec = (DVec)matExp.Multiply(vec); + resultMat.SetColumn(t, vec); + } } + result = resultMat.Values; } - result = resultMat.Values; - } - //出射面での境界条件を考慮した位相にするため、以下のように変更 (20220803) - for (int t = 0; t < Thicknesses.Length; t++) - for (int b = 0; b < beams.Length; b++) - result[t * beams.Length + b] *= Exp(PiI * (beams[b].P - 2 * kvac * Surface.Z) * Thicknesses[t]); - #endregion + //出射面での境界条件を考慮した位相にするため、以下のように変更 (20220803) + for (int t = 0; t < Thicknesses.Length; t++) + for (int b = 0; b < beams.Length; b++) + result[t * beams.Length + b] *= Exp(PiI * (beams[b].P - 2 * kvac * Surface.Z) * Thicknesses[t]); + #endregion - bwCBED.ReportProgress(Interlocked.Increment(ref count), reportString);//進捗状況を報告 - return (result, beams); - }).ToArray(); + bwEBSD.ReportProgress(Interlocked.Increment(ref count), reportString);//進捗状況を報告 + return (result, beams); + }).ToArray(); - count = 0; - bwCBED.ReportProgress(0, "Compiling disks"); + //count = 0; + //bwEBSD.ReportProgress(0, "Compiling disks"); - var directDiskIntensities = new double[Thicknesses.Length][]; - for (int t = 0; t < Thicknesses.Length; t++) - { - directDiskIntensities[t] = new double[BeamDirections.Length]; - for (int r = 0; r < directDiskIntensities[t].Length; r++) - if (diskAmplitude[r].result != null) - directDiskIntensities[t][r] = diskAmplitude[r].result[t * diskAmplitude[r].beams.Length + 0].MagnitudeSquared(); - } + var directDiskIntensities = new double[Thicknesses.Length][]; + for (int t = 0; t < Thicknesses.Length; t++) + { + directDiskIntensities[t] = new double[BeamDirections.Length]; + for (int r = 0; r < directDiskIntensities[t].Length; r++) + if (diskAmplitude[r].result != null) + directDiskIntensities[t][r] = diskAmplitude[r].result[t * diskAmplitude[r].beams.Length + 0].MagnitudeSquared(); + } - var directDiskPositions = new PointD[BeamDirections.Length]; - for (int r = 0; r < BeamDirections.Length; r++) - { - //var vec = BeamDirections[r] * new Vector3DBase(0, 0, kvac);//Ewald球中心(試料)から見た、逆格子ベクトルの方向 - var vec = kvac * BeamDirections[r];//Ewald球中心(試料)から見た、逆格子ベクトルの方向 - directDiskPositions[r] = new PointD(vec.X / vec.Z, vec.Y / vec.Z); //カメラ長 1 を想定した検出器上のピクセルの座標値を格納 - } - double xMax = directDiskPositions.Max(p => p.X), xMin = directDiskPositions.Min(p => p.X); - double yMax = directDiskPositions.Max(p => p.Y), yMin = directDiskPositions.Min(p => p.Y); + var directDiskPositions = new PointD[BeamDirections.Length]; + for (int r = 0; r < BeamDirections.Length; r++) + { + //var vec = BeamDirections[r] * new Vector3DBase(0, 0, kvac);//Ewald球中心(試料)から見た、逆格子ベクトルの方向 + var vec = kvac * BeamDirections[r];//Ewald球中心(試料)から見た、逆格子ベクトルの方向 + directDiskPositions[r] = new PointD(vec.X / vec.Z, vec.Y / vec.Z); //カメラ長 1 を想定した検出器上のピクセルの座標値を格納 + } + double xMax = directDiskPositions.Max(p => p.X), xMin = directDiskPositions.Min(p => p.X); + double yMax = directDiskPositions.Max(p => p.Y), yMin = directDiskPositions.Min(p => p.Y); - Parallel.For(0, BeamDirections.Length, r1 => - { - if (diskAmplitude[r1].result != null) + Parallel.For(0, BeamDirections.Length, r1 => { - for (int g = 1; g < diskAmplitude[r1].beams.Length; g++) + if (diskAmplitude[r1].result != null) { - //var vec = BeamDirections[r1] * (new Vector3DBase(0, 0, kvac) - diskAmplitude[r1].beams[g].Vec);//Ewald球中心(試料)から見た、逆格子ベクトルの方向 - var vec = kvac * BeamDirections[r1] - diskAmplitude[r1].beams[g].Vec;//Ewald球中心(試料)から見た、逆格子ベクトルの方向 - double posX = vec.X / vec.Z, posY = vec.Y / vec.Z; //カメラ長 1 を想定した検出器上のピクセルの座標値を格納 - if (posX < xMax && posX > xMin && posY < yMax && posY > yMin) + for (int g = 1; g < diskAmplitude[r1].beams.Length; g++) { - var r2 = getIndex(new PointD(posX, posY), directDiskPositions, width); - if (r2 >= 0 && directDiskIntensities[0][r2] != 0) - lock (lockObj1) - for (int t = 0; t < Thicknesses.Length; t++) - directDiskIntensities[t][r2] += diskAmplitude[r1].result[t * diskAmplitude[r1].beams.Length + g].MagnitudeSquared(); + var vec = kvac * BeamDirections[r1] - diskAmplitude[r1].beams[g].Vec;//Ewald球中心(試料)から見た、逆格子ベクトルの方向 + double posX = vec.X / vec.Z, posY = vec.Y / vec.Z; //カメラ長 1 を想定した検出器上のピクセルの座標値を格納 + if (posX < xMax && posX > xMin && posY < yMax && posY > yMin) + { + var r2 = getIndex(new PointD(posX, posY), directDiskPositions, width); + if (r2 >= 0 && directDiskIntensities[0][r2] != 0) + lock (lockObj1) + for (int t = 0; t < Thicknesses.Length; t++) + directDiskIntensities[t][r2] += diskAmplitude[r1].result[t * diskAmplitude[r1].beams.Length + g].MagnitudeSquared(); + } } } + //bwEBSD.ReportProgress(Interlocked.Increment(ref count) * 1000 / BeamDirections.Length, "Compiling disks"); + }); + + Disks[vIndex] = new CBED_Disk[Thicknesses.Length]; + for (int t = 0; t < Thicknesses.Length; t++) + { + Disks[vIndex][t] = new CBED_Disk([0, 0, 0], new Vector3DBase(0, 0, 0), Thicknesses[t], + directDiskIntensities[t].Select(intensity => new Complex(Math.Sqrt(intensity), 0)).ToArray()); + Disks[vIndex][t].Amplitudes = Disks[vIndex][t].RawAmplitudes; } - bwCBED.ReportProgress(Interlocked.Increment(ref count) * 1000 / BeamDirections.Length, "Compiling disks"); - }); - Disks = new CBED_Disk[Thicknesses.Length][]; - for (int t = 0; t < Thicknesses.Length; t++) - { - Disks[t] = [new CBED_Disk([0, 0, 0], new Vector3DBase(0, 0, 0), Thicknesses[t], - directDiskIntensities[t].Select(intensity => new Complex(Math.Sqrt(intensity), 0)).ToArray())]; - Disks[t][0].Amplitudes = Disks[t][0].RawAmplitudes; + if (bwEBSD.CancellationPending) + e.Cancel = true; } - - if (bwCBED.CancellationPending) - e.Cancel = true; } //与えられたposに最も近いインデックスを返す @@ -705,6 +761,7 @@ public Beam[] GetPrecessionElectronDiffraction(int maxNumOfBloch, double voltage var useEigen = EigenEnabled && maxNumOfBloch < 400; var stepP = Enumerable.Range(0, step).ToList().AsParallel().WithDegreeOfParallelism(useEigen ? Environment.ProcessorCount : Math.Max(1, Environment.ProcessorCount / 4)); + if (MaxNumOfBloch != maxNumOfBloch || AccVoltage != voltage || EigenValuesPED == null || EigenValuesPED.Length != step || EigenVectorsPED == null || EigenVectorsPED.Length != step || semiangle != SemianglePED || !baseRotation.Equals(BaseRotation)) { @@ -1342,7 +1399,7 @@ Complex Lenz(in PointD k, in PointD kq, in double defocus) { for (int x = 0; x < width; x++) { - var rVec = new PointD(-resolution * (x - cX), resolution * (y - cY)) + shift;//X座標はマイナス。 + var rVec = new PointD(resolution * (x - cX), -resolution * (y - cY)) + shift;//Y座標はマイナス。 for (int t = 0; t < Thicknesses.Length; t++) for (int d = 0; d < dLen; d++) { @@ -1514,7 +1571,7 @@ public void GetHRTEMImage(int BlochNum, double AccVol, Matrix3D rot, (double R, Parallel.For(0, divTotal, div => { int start = step * div, count = div == divTotal - 1 ? width * height - start : step; - var rVec = Enumerable.Range(start, count).SelectMany(n => new[] { -res * (n % width - cX) + shift.X, res * (n / width - cY) + shift.Y }).ToArray();//X座標はマイナス。 + var rVec = Enumerable.Range(start, count).SelectMany(n => new[] { res * (n % width - cX) + shift.X, -res * (n / width - cY) + shift.Y }).ToArray();//Y座標はマイナス。 var results = NativeWrapper.HRTEM_Solver(gPsi, gVec, gLenz, rVec, quasiMode); for (var i = 0; i < defLen; i++) Array.Copy(results, i * count, _images[t][i], start, count); @@ -1524,7 +1581,7 @@ public void GetHRTEMImage(int BlochNum, double AccVol, Matrix3D rot, (double R, { Parallel.For(0, width * height, n => { - PointD r = new(-(n % width - cX) * res + shift.X, (n / width - cY) * res + shift.Y), _vec = new(double.NaN, double.NaN);//X座標はマイナス。 + PointD r = new((n % width - cX) * res + shift.X, -(n / width - cY) * res + shift.Y), _vec = new(double.NaN, double.NaN);//Y座標はマイナス。 var sums = new Complex[defLen]; var exp = new Complex(0, 0); foreach (var (Psi, Vec, Lenz) in gList) @@ -1724,7 +1781,6 @@ public Beam[] Find_gVectors(Matrix3D baseRotation, Vector3DBase vecK0, int maxNu maxNumOfBloch = MaxNumOfBloch; var mat = baseRotation * Crystal.MatrixInverse.Transpose(); FrozenSet<(int h, int k, int l)> direction; - #region directionを初期化 if (Crystal.Symmetry.LatticeTypeStr == "F") direction = directionF; else if (Crystal.Symmetry.LatticeTypeStr == "A") direction = directionA; @@ -1773,7 +1829,6 @@ public Beam[] Find_gVectors(Matrix3D baseRotation, Vector3DBase vecK0, int maxNu var vLen2 = v.Length2; var (q, p) = (k0_2 - vLen2, 2 * Surface * v); - //if (Math.Abs(g.Z) < 0.1)//検証コード if (Math.Abs(q) < maxQ) beams.Add(new Beam(index, g, getU(AccVoltage, new Beam(index, g)), (q, p))); outer.Add((index, g.Length)); diff --git a/Crystallography/Crystal/Crystal.cs b/Crystallography/Crystal/Crystal.cs index 4530582..90e54ef 100644 --- a/Crystallography/Crystal/Crystal.cs +++ b/Crystallography/Crystal/Crystal.cs @@ -877,6 +877,43 @@ public static bool CheckIrreducible(int a, int b, int c) return true; } + /// + /// g(hkl)񂩂ǂ𔻒 + /// + /// + /// + /// + public static bool CheckIrreducible((int h, int k, int l) index1, (int h, int k, int l) index2) + { + if (index1.h == index2.h && index1.k == index2.k && index1.l == index2.l) + return false; + + int coeff1 = 0, coeff2 = 0; + if (index1.h != 0 && index2.h != 0) + { + coeff1 = index1.h / index2.h; + coeff2 = index2.h / index1.h; + } + else if (index1.k != 0 && index2.k != 0) + { + coeff1 = index1.k / index2.k; + coeff2 = index2.k / index1.k; + } + else if (index1.l != 0 && index2.l != 0) + { + coeff1 = index1.l / index2.l; + coeff2 = index2.l / index1.l; + } + + if (Math.Abs(coeff1) > 1) + return !(index2.h * coeff1 == index1.h && index2.k * coeff1 == index1.k && index2.l * coeff1 == index1.l); + else if (Math.Abs(coeff2) > 1) + return !(index1.h * coeff2 == index2.h && index1.k * coeff2 == index2.k && index1.l * coeff2 == index2.l); + else + return true; + } + + #endregion 􉽊w֘A #region xNǧvZ @@ -926,11 +963,25 @@ public void SetVectorOfAxis(int uMax, int vMax, int wMax) /// Ŏw肳ꂽw̖ʃxNgvZAVectorOfPlaneɊi[ /// /// - public void SetVectorOfPlane((int H, int K, int L)[] indices) + public void SetVectorOfPlane((int h, int k, int l)[] indices, WaveSource waveSource) { VectorOfPlane = []; - foreach (var (H, K, L) in indices) - VectorOfPlane.Add(new Vector3D(H * A_Star + K * B_Star + L * C_Star) { Text = $"({H}{K}{L})" }); + foreach (var (h, k, l) in indices) + { + var vec = new Vector3D(h * A_Star + k * B_Star + l * C_Star); + vec.F = GetStructureFactor(waveSource, Atoms, (h, k, l), vec.Length2 / 4.0); + vec.RawIntensity = vec.F.MagnitudeSquared(); + vec.Text = $"({h}{k}{l})"; + vec.Index = (h, k, l); + VectorOfPlane.Add(vec); + } + + if (VectorOfPlane.Count > 0) + { + var max = VectorOfPlane.Max(v => v.RawIntensity); + if (max > 0) + VectorOfPlane.ForEach(v => v.RelativeIntensity = v.RawIntensity / max); + } } /// @@ -939,28 +990,16 @@ public void SetVectorOfPlane((int H, int K, int L)[] indices) /// /// /// - public void SetVectorOfPlane(int hMax, int kMax, int lMax) + public void SetVectorOfPlane(int hMax, int kMax, int lMax, WaveSource waveSource) { - VectorOfPlane = []; - Vector3D vec; - - vec = CalcHklVector(1, 0, 0); vec = vec * GetLengthPlane(1, 0, 0) / vec.d; vec.Text = "(100)"; VectorOfPlane.Add(vec); - vec = CalcHklVector(0, 1, 0); vec = vec * GetLengthPlane(0, 1, 0) / vec.d; vec.Text = "(010)"; VectorOfPlane.Add(vec); - vec = CalcHklVector(0, 0, 1); vec = vec * GetLengthPlane(0, 0, 1) / vec.d; vec.Text = "(001)"; VectorOfPlane.Add(vec); - vec = CalcHklVector(-1, 0, 0); vec = vec * GetLengthPlane(-1, 0, 0) / vec.d; vec.Text = "(-100)"; VectorOfPlane.Add(vec); - vec = CalcHklVector(0, -1, 0); vec = vec * GetLengthPlane(0, -1, 0) / vec.d; vec.Text = "(0-10)"; VectorOfPlane.Add(vec); - vec = CalcHklVector(0, 0, -1); vec = vec * GetLengthPlane(0, 0, -1) / vec.d; vec.Text = "(00-1)"; VectorOfPlane.Add(vec); + var indices = new List<(int h, int k, int l)> { (1, 0, 0), (0, 1, 0), (0, 0, 1), (-1, 0, 0), (0, -1, 0), (0, 0, -1) }; for (int h = -hMax; h <= hMax; h++) for (int k = -kMax; k <= kMax; k++) for (int l = -lMax; l <= lMax; l++) - if (CheckIrreducible(h, k, l) && !(h * k == 0 && k * l == 0 && l * h == 0)) - { - vec = CalcHklVector(h, k, l); - vec = vec * GetLengthPlane(h, k, l) / vec.d; - vec.Text = $"({h}{k}{l})"; - VectorOfPlane.Add(vec); - } + indices.Add((h, k, l)); + + SetVectorOfPlane([.. indices], waveSource); } /// @@ -990,7 +1029,6 @@ public void SetPlanes(double dMax, double dMin, bool excludeEquivalentPlane, boo var shift = directions.Select(dir => (MatrixInverse * dir).Length).Max(); - var maxNum = _maxNum; 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ȂƂɒ @@ -1218,8 +1256,8 @@ public void SetPlanes() /// /// /// - public void SetVectorOfG(double dMin, WaveSource wavesource, bool excludeLatticeCondition = true) - => SetVectorOfG(dMin,double.PositiveInfinity,wavesource,excludeLatticeCondition); + public void SetVectorOfG(double dMin, WaveSource wavesource, int maxNum = 25000) + => SetVectorOfG(dMin, double.PositiveInfinity, wavesource, maxNum); /// /// dMinȏAdMaxȉ͈̔͂ŋtiqxNgvZAwavesorceɏ]āA\qvZ @@ -1227,7 +1265,7 @@ public void SetVectorOfG(double dMin, WaveSource wavesource, bool excludeLattice /// /// /// - public void SetVectorOfG(double dMin, double dMax, WaveSource wavesource, bool excludeLatticeCondition = true) + public void SetVectorOfG(double dMin, double dMax, WaveSource wavesource, int maxNum = 25000) { if (double.IsNaN(dMin)) return; @@ -1268,13 +1306,13 @@ public void SetVectorOfG(double dMin, double dMax, WaveSource wavesource, bool e var shift = directions.Select(dir => (MatrixInverse * dir).Length).Max(); - var maxGnum = 250000; + //var maxNum = 250000; var zeroKey = (255 << 20) + (255 << 10) + 255; - var gHash = new HashSet((int)(maxGnum * 1.5)) { zeroKey }; - var gList = new List<(int key, double x, double y, double z, double len)>((int)(maxGnum * 1.5)) { (zeroKey, 0, 0, 0, 0) }; + var gHash = new HashSet((int)(maxNum * 1.5)) { zeroKey }; + var gList = new List<(int key, double x, double y, double z, double len)>((int)(maxNum * 1.5)) { (zeroKey, 0, 0, 0, 0) }; int start = 0, end = 1; var outer = CollectionsMarshal.AsSpan(gList)[start..end]; - while (gList.Count < maxGnum && outer.Length > 0) + while (gList.Count < maxNum && outer.Length > 0) { foreach (var (key1, _, _, _, _) in outer) { @@ -1498,6 +1536,77 @@ public void ReCoordinateAtom() [XmlIgnore] private static readonly Complex TwoPiI = 2 * Complex.ImaginaryOne * Math.PI; + //(h,k,l)̍\Uq(MUU)F (f) vZ (h, k, l񐮐̏ꍇɑΉeXgR[h) + /// + /// \q߂ s2̒Pʂnm^-2 + /// + /// + /// + /// + /// + /// + /// Pʂnm^-2 + /// + public static Complex GetStructureFactor(WaveSource wave, Atoms[] atomsArray, (double h, double k, double l) index, double s2) + { + #region + (double h, double k, double l) = index; + //s2 = (sin(theta)/ramda)^2 = 1 / 4 /d^2 + if (atomsArray.Length == 0) + return new Complex(0, 0); + Complex F = 0, f = 0; + int atomicNum = -1, subNum = -1; + + foreach (var atoms in atomsArray) + { + if (wave == WaveSource.Electron) + { + if (atoms.AtomicNumber != atomicNum || atoms.SubNumberElectron != subNum) + { + f = new Complex(atoms.GetAtomicScatteringFactorForElectron(s2), 0); + atomicNum = atoms.AtomicNumber; + subNum = atoms.SubNumberElectron; + } + } + else if (wave == WaveSource.Xray) + { + if (atoms.AtomicNumber != atomicNum || atoms.SubNumberXray != subNum) + { + f = new Complex(atoms.GetAtomicScatteringFactorForXray(s2), 0); + atomicNum = atoms.AtomicNumber; + subNum = atoms.SubNumberXray; + } + } + else + f = atoms.GetAtomicScatteringFactorForNeutron(); + + + if (atoms.Dsf.UseIso) + { + var T = Math.Exp(-atoms.Dsf.Biso * s2); + if (double.IsNaN(T)) + T = 1; + foreach (var atom in atoms.Atom) + F += f * T * Complex.Exp(-TwoPiI * (h * atom.X + k * atom.Y + l * atom.Z)); + } + else + { + foreach (var atom in atoms.Atom) + { + var (H, K, L) = atom.Operation.ConvertPlaneIndex(h, k, l); + var T = Math.Exp(-(atoms.Dsf.B11 * H * H + atoms.Dsf.B22 * K * K + atoms.Dsf.B33 * L * L + + 2 * atoms.Dsf.B12 * H * K + 2 * atoms.Dsf.B23 * K * L + 2 * atoms.Dsf.B31 * L * H)); + if (double.IsNaN(T)) + T = 1; + F += f * T * Complex.Exp(-TwoPiI * (h * atom.X + k * atom.Y + l * atom.Z)); + } + } + } + return F;// Complex(Real, Inverse); + #endregion + } + + //(h,k,l)̍\Uq(MUU)F (f) vZ /// /// \q߂ s2̒Pʂnm^-2 diff --git a/Crystallography/Crystal/PolyCrystal.cs b/Crystallography/Crystal/PolyCrystal.cs index 9fe6a9a..fb67d79 100644 --- a/Crystallography/Crystal/PolyCrystal.cs +++ b/Crystallography/Crystal/PolyCrystal.cs @@ -8,1267 +8,1266 @@ using System.Threading.Tasks; using System.Xml.Serialization; -namespace Crystallography +namespace Crystallography; + +[Serializable()] +public class Crystallite { - [Serializable()] - public class Crystallite + #region フィールド、プロパティ + + public static Matrix3D TiltMatrix = Matrix3D.Rot(new Vector3DBase(0.2, 0.1, 0), Math.PI / 180 * 5);//適当に傾ける行列を作成 + + [XmlIgnoreAttribute] + public Crystal BaseCrystal = null; + + /// + /// 角度分解能 Degree単位 + /// + [XmlIgnoreAttribute] + public double AngleResolution { get => BaseCrystal.AngleResolution; set => BaseCrystal.AngleResolution = value; } + + /// + /// 一つの結晶子が受け持つ角度を分割する数 + /// + [XmlIgnoreAttribute] + public int SubDiv { get => BaseCrystal.SubDivision; set => BaseCrystal.SubDivision = value; } + + /// + /// 結晶子のサイズ + /// + [XmlIgnoreAttribute] + public double GrainSize { get => BaseCrystal.GrainSize; set => BaseCrystal.GrainSize = value; } + + /// + /// 多結晶体全体のRotation  + /// + public Matrix3D WholeRotation = Matrix3D.IdentityMatrix; + + public int SquareDiv => (int)(90.0 / BaseCrystal.AngleResolution); + public int RotationDiv => (int)(360.0 / BaseCrystal.AngleResolution); + + /// + /// 全結晶子の数 + /// + public int TotalCrystalline => 6 * SquareDiv * SquareDiv * RotationDiv; + + public int ImageWidh { get; set; } + public int ImageHeight { get; set; } + + /// + /// [n][] n番目の結晶方位について、エワルド球に近い逆格子ベクトルの番号 + /// + public int[][] ValidIndex; + + /// + /// [n][m][] n番目の結晶方位の、m番目の逆格子ベクトルが、考慮すべきSubRotation番号 + /// + //public ushort[][][] ValidSubRotNum; + + /// + /// Pixel[n].Keys:n番目の角度範囲の結晶子が寄与する画素の番号 + /// Pixel[n].Values:n番目の角度範囲の結晶子が寄与する画素の強度 + /// + public (int Index, double Intensity)[][] Pixel; + + /// + /// n番目の角度範囲の結晶子が受け持つ立体角 + /// + public double[] SolidAngle; + + /// + /// n番目の角度範囲の結晶子の濃度 + /// + public double[] Density; + + //[n][angle][] n番目の逆格子ベクトルが ある回転角(angle)でエワルド球に一致したとき、そのピクセルを原点とした、強度順で並び替えたピクセル位置 + public int[][][] SpotShapesSortedIndex; + + //SpotShapesSortedIndexにおける一周(360°)の分割数 + public int SpotShapesAngleDivision = 360; + + public double[] DeviationThreshold; + + /// + /// 結晶子の回転行列 + /// + public Matrix3D[] Rotations = null; + + private Matrix3D[] Rotations1 = null; + private Matrix3D[] Rotations2 = null; + + /// + /// 結晶子の回転行列の前半 (z軸の方向に対応) + /// + private Matrix3D[] SubRot1; + + /// + /// 結晶の回転行列の後半 (Z軸の回転に対応) + /// + private Matrix3D[] SubRot2; + + /// + /// 全逆格子ベクトルの数 + /// + public int G_VectorNumber => G != null ? G.Length : -1; + + /// + /// Vec: 逆格子ベクトル + /// Hk1, Hk2, Hk3: 逆格子ベクトルの半値幅 + /// Intensity: 逆格子ベクトルの強度 + /// + public (double X, double Y, double Z, double Hk1, double Hk2, double Hk3, double Intensity, double Intensity2)[] G; + + #endregion フィールド、プロパティ + + public event ProgressChangedEventHandler ProgressChanged; + + [XmlIgnoreAttribute] + readonly Stopwatch stopwatch = new Stopwatch(); + //private object lockObj = new object(); + public Crystallite() { - #region フィールド、プロパティ - - public static Matrix3D TiltMatrix = Matrix3D.Rot(new Vector3DBase(0.2, 0.1, 0), Math.PI / 180 * 5);//適当に傾ける行列を作成 - - [XmlIgnoreAttribute] - public Crystal BaseCrystal = null; - - /// - /// 角度分解能 Degree単位 - /// - [XmlIgnoreAttribute] - public double AngleResolution { get => BaseCrystal.AngleResolution; set => BaseCrystal.AngleResolution = value; } - - /// - /// 一つの結晶子が受け持つ角度を分割する数 - /// - [XmlIgnoreAttribute] - public int SubDiv { get => BaseCrystal.SubDivision; set => BaseCrystal.SubDivision = value; } - - /// - /// 結晶子のサイズ - /// - [XmlIgnoreAttribute] - public double GrainSize { get => BaseCrystal.GrainSize; set => BaseCrystal.GrainSize = value; } - - /// - /// 多結晶体全体のRotation  - /// - public Matrix3D WholeRotation = Matrix3D.IdentityMatrix; - - public int SquareDiv => (int)(90.0 / BaseCrystal.AngleResolution); - public int RotationDiv => (int)(360.0 / BaseCrystal.AngleResolution); - - /// - /// 全結晶子の数 - /// - public int TotalCrystalline => 6 * SquareDiv * SquareDiv * RotationDiv; - - public int ImageWidh { get; set; } - public int ImageHeight { get; set; } - - /// - /// [n][] n番目の結晶方位について、エワルド球に近い逆格子ベクトルの番号 - /// - public int[][] ValidIndex; - - /// - /// [n][m][] n番目の結晶方位の、m番目の逆格子ベクトルが、考慮すべきSubRotation番号 - /// - //public ushort[][][] ValidSubRotNum; - - /// - /// Pixel[n].Keys:n番目の角度範囲の結晶子が寄与する画素の番号 - /// Pixel[n].Values:n番目の角度範囲の結晶子が寄与する画素の強度 - /// - public (int Index, double Intensity)[][] Pixel; - - /// - /// n番目の角度範囲の結晶子が受け持つ立体角 - /// - public double[] SolidAngle; - - /// - /// n番目の角度範囲の結晶子の濃度 - /// - public double[] Density; - - //[n][angle][] n番目の逆格子ベクトルが ある回転角(angle)でエワルド球に一致したとき、そのピクセルを原点とした、強度順で並び替えたピクセル位置 - public int[][][] SpotShapesSortedIndex; - - //SpotShapesSortedIndexにおける一周(360°)の分割数 - public int SpotShapesAngleDivision = 360; - - public double[] DeviationThreshold; - - /// - /// 結晶子の回転行列 - /// - public Matrix3D[] Rotations = null; - - private Matrix3D[] Rotations1 = null; - private Matrix3D[] Rotations2 = null; - - /// - /// 結晶子の回転行列の前半 (z軸の方向に対応) - /// - private Matrix3D[] SubRot1; - - /// - /// 結晶の回転行列の後半 (Z軸の回転に対応) - /// - private Matrix3D[] SubRot2; - - /// - /// 全逆格子ベクトルの数 - /// - public int G_VectorNumber => G != null ? G.Length : -1; - - /// - /// Vec: 逆格子ベクトル - /// Hk1, Hk2, Hk3: 逆格子ベクトルの半値幅 - /// Intensity: 逆格子ベクトルの強度 - /// - public (double X, double Y, double Z, double Hk1, double Hk2, double Hk3, double Intensity, double Intensity2)[] G; - - #endregion フィールド、プロパティ - - public event ProgressChangedEventHandler ProgressChanged; - - [XmlIgnoreAttribute] - readonly Stopwatch stopwatch = new Stopwatch(); - //private object lockObj = new object(); - public Crystallite() - { - } + } - public Crystallite(Crystal baseCrystal) - : this() - { - BaseCrystal = baseCrystal; - setCrystallineRotation(); - setCrystallineSolidAngle(); - Density = Enumerable.Repeat(1.0, TotalCrystalline).ToArray(); - if (vec == null || vec[0].Length != SquareDiv) - initializeVec(); - } + public Crystallite(Crystal baseCrystal) + : this() + { + BaseCrystal = baseCrystal; + setCrystallineRotation(); + setCrystallineSolidAngle(); + Density = Enumerable.Repeat(1.0, TotalCrystalline).ToArray(); + if (vec == null || vec[0].Length != SquareDiv) + initializeVec(); + } - public Crystallite(Crystal baseCrystal, double[] density) - : this() + public Crystallite(Crystal baseCrystal, double[] density) + : this() + { + BaseCrystal = baseCrystal; + setCrystallineRotation(); + setCrystallineSolidAngle(); + if (TotalCrystalline == density.Length) + Density = density; + else { - BaseCrystal = baseCrystal; - setCrystallineRotation(); - setCrystallineSolidAngle(); - if (TotalCrystalline == density.Length) - Density = density; - else - { - Density = new double[TotalCrystalline]; - for (int i = 0; i < TotalCrystalline; i++) - Density[i] = 1; - } - if (vec == null || vec[0].Length != SquareDiv) - initializeVec(); + Density = new double[TotalCrystalline]; + for (int i = 0; i < TotalCrystalline; i++) + Density[i] = 1; } + if (vec == null || vec[0].Length != SquareDiv) + initializeVec(); + } - public void SetGVector(AreaDetector detector, bool applyTiltMatrix = true, bool removeZeroIntensity = true, bool calcSpotShape = true) - { - if (BaseCrystal != null) - SetGVector(BaseCrystal, detector, applyTiltMatrix, removeZeroIntensity, calcSpotShape); + public void SetGVector(AreaDetector detector, bool applyTiltMatrix = true, bool removeZeroIntensity = true, bool calcSpotShape = true) + { + if (BaseCrystal != null) + SetGVector(BaseCrystal, detector, applyTiltMatrix, removeZeroIntensity, calcSpotShape); + } + + /// + /// 結晶の逆格子ベクトルを初期化 + /// + /// + /// + /// + /// + /// + public void SetGVector(Crystal crystal, AreaDetector detector, bool applyTiltMatrix = true, bool removeZeroIntensity = true, bool calcSpotShape = true) + { + ImageWidh = detector.ImageWidth; + ImageHeight = detector.ImageHeight; + + double length = 0; + if (detector.MaskedArea == null || detector.MaskedArea.Length != detector.ImageWidth * detector.ImageHeight) + { //画面の四隅のエワルド球で最もZ値が大きいものを算出 + double left = -detector.Center.X * detector.Resolution; + double right = (detector.ImageWidth - detector.Center.X) * detector.Resolution; + double top = -detector.Center.Y * detector.Resolution; + double bottom = (detector.ImageHeight - detector.Center.Y) * detector.Resolution; + length = new[]{ + Math.Sqrt(left * left + top * top), Math.Sqrt(left * left + bottom * bottom), + Math.Sqrt(right * right + top * top), Math.Sqrt(right * right + bottom * bottom) + }.Max(); + } + else + { //マスクされていない中で最もZ値が大きいものを算出 + double max = double.NegativeInfinity; + for (int h = 0; h < detector.ImageHeight; h++) + for (int w = 0; w < detector.ImageWidth; w++) + if (!detector.MaskedArea[h * detector.ImageWidth + w]) + max = Math.Max(Math.Sqrt((h - detector.Center.Y) * (h - detector.Center.Y) + (w - detector.Center.X) * (w - detector.Center.X)) * detector.Resolution, max); + length = max; } + crystal.SetVectorOfG(detector.WaveLength / 2 / Math.Sin(Math.Atan(length / detector.CameraLength) / 2.0), detector.WaveSource); + if (crystal.VectorOfG.Length == 0) + return; - /// - /// 結晶の逆格子ベクトルを初期化 - /// - /// - /// - /// - /// - /// - public void SetGVector(Crystal crystal, AreaDetector detector, bool applyTiltMatrix = true, bool removeZeroIntensity = true, bool calcSpotShape = true) - { - ImageWidh = detector.ImageWidth; - ImageHeight = detector.ImageHeight; - - double length = 0; - if (detector.MaskedArea == null || detector.MaskedArea.Length != detector.ImageWidth * detector.ImageHeight) - { //画面の四隅のエワルド球で最もZ値が大きいものを算出 - double left = -detector.Center.X * detector.Resolution; - double right = (detector.ImageWidth - detector.Center.X) * detector.Resolution; - double top = -detector.Center.Y * detector.Resolution; - double bottom = (detector.ImageHeight - detector.Center.Y) * detector.Resolution; - length = new[]{ - Math.Sqrt(left * left + top * top), Math.Sqrt(left * left + bottom * bottom), - Math.Sqrt(right * right + top * top), Math.Sqrt(right * right + bottom * bottom) - }.Max(); + var temp = new List(); + foreach (var g in crystal.VectorOfG) + if (removeZeroIntensity) + { + if (g.Extinction.Length == 0) + temp.Add(g); } else - { //マスクされていない中で最もZ値が大きいものを算出 - double max = double.NegativeInfinity; - for (int h = 0; h < detector.ImageHeight; h++) - for (int w = 0; w < detector.ImageWidth; w++) - if (!detector.MaskedArea[h * detector.ImageWidth + w]) - max = Math.Max(Math.Sqrt((h - detector.Center.Y) * (h - detector.Center.Y) + (w - detector.Center.X) * (w - detector.Center.X)) * detector.Resolution, max); - length = max; + { + var s = g.Extinction; + if (s.Length == 0 || (s[0] != "I" && s[0] != "F" && s[0] != "A" && s[0] != "B" && s[0] != "C" && s[0] != "R")) + temp.Add(g); } - crystal.SetVectorOfG(detector.WaveLength / 2 / Math.Sin(Math.Atan(length / detector.CameraLength) / 2.0), detector.WaveSource); - if (crystal.VectorOfG.Length == 0) - return; - var temp = new List(); - foreach (var g in crystal.VectorOfG) - if (removeZeroIntensity) - { - if (g.Extinction.Length == 0) - temp.Add(g); - } - else - { - var s = g.Extinction; - if (s.Length == 0 || (s[0] != "I" && s[0] != "F" && s[0] != "A" && s[0] != "B" && s[0] != "C" && s[0] != "R")) - temp.Add(g); - } + crystal.VectorOfG = temp.ToArray(); - crystal.VectorOfG = temp.ToArray(); + G = new (double X, double Y, double Z, double Hk1, double Hk2, double Hk3, double Intensity, double Intensity2)[crystal.VectorOfG.Length]; - G = new (double X, double Y, double Z, double Hk1, double Hk2, double Hk3, double Intensity, double Intensity2)[crystal.VectorOfG.Length]; + for (int k = 0; k < crystal.VectorOfG.Length; k++) + { + var vec = applyTiltMatrix ? + TiltMatrix * crystal.VectorOfG[k] : + crystal.VectorOfG[k];//傾き行列をかけて置く + G[k].X = vec.X; + G[k].Y = vec.Y; + G[k].Z = vec.Z; - for (int k = 0; k < crystal.VectorOfG.Length; k++) - { - var vec = applyTiltMatrix ? - TiltMatrix * crystal.VectorOfG[k] : - crystal.VectorOfG[k];//傾き行列をかけて置く - G[k].X = vec.X; - G[k].Y = vec.Y; - G[k].Z = vec.Z; - - double cos2theta = (1 - crystal.VectorOfG[k].Length2 * detector.WaveLength * detector.WaveLength / 2.0);//cos2theta = 1-2*(sinTheta)^2 = 1 - 2* ( wavelentgh^2/d^2 / 4) - G[k].Intensity = crystal.VectorOfG[k].RelativeIntensity * (1 + cos2theta * cos2theta);//トムソン散乱の補正 - - double l2 = vec.Length2; - - double ewaldR = 1 / detector.WaveLength, ewaldR2 = ewaldR * ewaldR; - double monochromaticity2 = detector.Monochromaticity * detector.Monochromaticity; - double reciprocalPointSize = 1 / BaseCrystal.GrainSize / 2, reciprocalPointSize2 = reciprocalPointSize * reciprocalPointSize; - double vol = BaseCrystal.GrainSize * BaseCrystal.GrainSize * BaseCrystal.GrainSize; - - //半値幅を保存 - double convergenceHK = Math.Sin(detector.Convergence / 2) / detector.WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸垂直な方向) - G[k].Hk2 = reciprocalPointSize2 + convergenceHK * convergenceHK; // (-y,x,0)方向の半値幅 - G[k].Hk1 = G[k].Hk2 + monochromaticity2 * l2 * (1 - l2 / 4 / ewaldR2);//(x,y,0)方向の半値幅 - G[k].Hk3 = reciprocalPointSize2 + monochromaticity2 * l2 * l2 / 4 / ewaldR2;// (0,0,z)方向の半値幅 - - G[k].Intensity2 = 1 / Math.Sqrt(G[k].Hk1 * 1000 * G[k].Hk2 * 1000 * G[k].Hk3 * 1000) * vol * G[k].Intensity; - } + double cos2theta = (1 - crystal.VectorOfG[k].Length2 * detector.WaveLength * detector.WaveLength / 2.0);//cos2theta = 1-2*(sinTheta)^2 = 1 - 2* ( wavelentgh^2/d^2 / 4) + G[k].Intensity = crystal.VectorOfG[k].RelativeIntensity * (1 + cos2theta * cos2theta);//トムソン散乱の補正 - //最大強度を規格化 - double maxInt = G.Max(g => g.Intensity2) / 1000; - DeviationThreshold = new double[G.Length]; - for (int i = 0; i < G.Length; i++) - { - G[i].Intensity2 /= maxInt; - DeviationThreshold[i] = Math.Max(3, Math.Log10(G[i].Intensity2) * 3);//最小で3, 最大で9 - } - if (calcSpotShape) - setSpotShapes(detector); - } + double l2 = vec.Length2; - /// - /// 各結晶子が受け持つ - /// - /// - public void setSpotShapes(AreaDetector detector) - { - SpotShapesSortedIndex = new int[G.Length][][]; + double ewaldR = 1 / detector.WaveLength, ewaldR2 = ewaldR * ewaldR; + double monochromaticity2 = detector.Monochromaticity * detector.Monochromaticity; + double reciprocalPointSize = 1 / BaseCrystal.GrainSize / 2, reciprocalPointSize2 = reciprocalPointSize * reciprocalPointSize; + double vol = BaseCrystal.GrainSize * BaseCrystal.GrainSize * BaseCrystal.GrainSize; - Parallel.For(0, G.Length, gNum => - { - SpotShapesSortedIndex[gNum] = new int[SpotShapesAngleDivision][]; + //半値幅を保存 + double convergenceHK = Math.Sin(detector.Convergence / 2) / detector.WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸垂直な方向) + G[k].Hk2 = reciprocalPointSize2 + convergenceHK * convergenceHK; // (-y,x,0)方向の半値幅 + G[k].Hk1 = G[k].Hk2 + monochromaticity2 * l2 * (1 - l2 / 4 / ewaldR2);//(x,y,0)方向の半値幅 + G[k].Hk3 = reciprocalPointSize2 + monochromaticity2 * l2 * l2 / 4 / ewaldR2;// (0,0,z)方向の半値幅 - //エワルド球面に一致したときの、ダイレクトスポットからこの逆格子点までの実距離 + G[k].Intensity2 = 1 / Math.Sqrt(G[k].Hk1 * 1000 * G[k].Hk2 * 1000 * G[k].Hk3 * 1000) * vol * G[k].Intensity; + } - double gX = G[gNum].X, gY = G[gNum].Y, gZ = G[gNum].Z, gLength = Math.Sqrt(gX * gX + gY * gY + gZ * gZ); - double length = Math.Tan(detector.WaveLength * gLength) * detector.CameraLength; - double xyLength = Math.Sin(detector.WaveLength * gLength) / detector.WaveLength, xyLength2 = xyLength * xyLength; - double z = 1 / detector.WaveLength * (1 - Math.Cos(detector.WaveLength * gLength)); + //最大強度を規格化 + double maxInt = G.Max(g => g.Intensity2) / 1000; + DeviationThreshold = new double[G.Length]; + for (int i = 0; i < G.Length; i++) + { + G[i].Intensity2 /= maxInt; + DeviationThreshold[i] = Math.Max(3, Math.Log10(G[i].Intensity2) * 3);//最小で3, 最大で9 + } + if (calcSpotShape) + setSpotShapes(detector); + } - //角度分割 - for (int angle = 0; angle < SpotShapesAngleDivision; angle++) - { - double originX = length / detector.Resolution * Math.Cos(angle / 180.0 * Math.PI) + detector.Center.X; - double originY = -length / detector.Resolution * Math.Sin(angle / 180.0 * Math.PI) + detector.Center.Y; + /// + /// 各結晶子が受け持つ + /// + /// + public void setSpotShapes(AreaDetector detector) + { + SpotShapesSortedIndex = new int[G.Length][][]; - double x = xyLength * Math.Cos(angle / 180.0 * Math.PI); - double y = xyLength * Math.Sin(angle / 180.0 * Math.PI); + Parallel.For(0, G.Length, gNum => + { + SpotShapesSortedIndex[gNum] = new int[SpotShapesAngleDivision][]; - var pixels = new Dictionary(); + //エワルド球面に一致したときの、ダイレクトスポットからこの逆格子点までの実距離 - for (int devX = -4; devX <= 4; devX++) - for (int devY = -4; devY <= 4; devY++) - { - Vector3DBase v = detector.convertClientToReciprocalSpace(devX + originX, devY + originY); - double temp1 = x * v.X + y * v.Y - xyLength2; - double temp2 = x * v.Y - y * v.X; - double temp3 = z - v.Z; - double dev2 = temp1 * temp1 / xyLength2 / G[gNum].Hk1 + temp2 * temp2 / xyLength2 / G[gNum].Hk2 + temp3 * temp3 / G[gNum].Hk3; - if (dev2 < DeviationThreshold[gNum] * 1.5) - pixels.Add(devY * detector.ImageHeight + devX, -dev2); - } - var vs2 = pixels.OrderByDescending(e => e.Value); - List index = new List(); - foreach (var v in vs2) - index.Add(v.Key); - SpotShapesSortedIndex[gNum][angle] = index.ToArray(); - } - } - ); - /* - //同じ配列が大量に出てくるので、メモリ節約のために、まとめる + double gX = G[gNum].X, gY = G[gNum].Y, gZ = G[gNum].Z, gLength = Math.Sqrt(gX * gX + gY * gY + gZ * gZ); + double length = Math.Tan(detector.WaveLength * gLength) * detector.CameraLength; + double xyLength = Math.Sin(detector.WaveLength * gLength) / detector.WaveLength, xyLength2 = xyLength * xyLength; + double z = 1 / detector.WaveLength * (1 - Math.Cos(detector.WaveLength * gLength)); - for (int i = 0; i < G_Vector.Length * SpotShapesAngleDivision - 1; i++) + //角度分割 + for (int angle = 0; angle < SpotShapesAngleDivision; angle++) { - int gNum1 = i / SpotShapesAngleDivision, angle1 = i % SpotShapesAngleDivision; + double originX = length / detector.Resolution * Math.Cos(angle / 180.0 * Math.PI) + detector.Center.X; + double originY = -length / detector.Resolution * Math.Sin(angle / 180.0 * Math.PI) + detector.Center.Y; - for (int j = i + 1; j < G_Vector.Length * SpotShapesAngleDivision; j++) - { - int gNum2 = j / SpotShapesAngleDivision, angle2 = j % SpotShapesAngleDivision; - if (SpotShapesSortedIndex[gNum1][angle1].Length == SpotShapesSortedIndex[gNum2][angle2].Length) + double x = xyLength * Math.Cos(angle / 180.0 * Math.PI); + double y = xyLength * Math.Sin(angle / 180.0 * Math.PI); + + var pixels = new Dictionary(); + + for (int devX = -4; devX <= 4; devX++) + for (int devY = -4; devY <= 4; devY++) { - bool flag = true; - for (int k = 0; k < SpotShapesSortedIndex[gNum1][angle1].Length && flag; k++) - if (SpotShapesSortedIndex[gNum1][angle1][k] != SpotShapesSortedIndex[gNum2][angle2][k]) - flag = false; - if (flag) - { - SpotShapesSortedIndex[gNum1][angle1] = SpotShapesSortedIndex[gNum2][angle2]; - break; - } + Vector3DBase v = detector.convertClientToReciprocalSpace(devX + originX, devY + originY); + double temp1 = x * v.X + y * v.Y - xyLength2; + double temp2 = x * v.Y - y * v.X; + double temp3 = z - v.Z; + double dev2 = temp1 * temp1 / xyLength2 / G[gNum].Hk1 + temp2 * temp2 / xyLength2 / G[gNum].Hk2 + temp3 * temp3 / G[gNum].Hk3; + if (dev2 < DeviationThreshold[gNum] * 1.5) + pixels.Add(devY * detector.ImageHeight + devX, -dev2); } - } + var vs2 = pixels.OrderByDescending(e => e.Value); + List index = new List(); + foreach (var v in vs2) + index.Add(v.Key); + SpotShapesSortedIndex[gNum][angle] = index.ToArray(); } - GC.Collect(); - */ } - - #region お蔵入り中 + ); /* - public static object lockObject = new object(); - private static Random rn = new Random(); - - /// - /// - /// - /// - /// - /// - /// - public static Matrix3D[] GenerateBiasedOrientation(Matrix3D seed, int number, double directionalDensity) + //同じ配列が大量に出てくるので、メモリ節約のために、まとめる + + for (int i = 0; i < G_Vector.Length * SpotShapesAngleDivision - 1; i++) { - Matrix3D[] mat = new Matrix3D[number]; - ParallelOptions p = new ParallelOptions(); - p.MaxDegreeOfParallelism = Environment.ProcessorCount; - Parallel.For(0, number, p, i => + int gNum1 = i / SpotShapesAngleDivision, angle1 = i % SpotShapesAngleDivision; + + for (int j = i + 1; j < G_Vector.Length * SpotShapesAngleDivision; j++) { - double r1, r2, r3; - lock (lockObject) + int gNum2 = j / SpotShapesAngleDivision, angle2 = j % SpotShapesAngleDivision; + if (SpotShapesSortedIndex[gNum1][angle1].Length == SpotShapesSortedIndex[gNum2][angle2].Length) { - r1 = rn.NextDouble(); - r2 = rn.NextDouble() * 2 * Math.PI; - r3 = rn.NextDouble(); + bool flag = true; + for (int k = 0; k < SpotShapesSortedIndex[gNum1][angle1].Length && flag; k++) + if (SpotShapesSortedIndex[gNum1][angle1][k] != SpotShapesSortedIndex[gNum2][angle2][k]) + flag = false; + if (flag) + { + SpotShapesSortedIndex[gNum1][angle1] = SpotShapesSortedIndex[gNum2][angle2]; + break; + } } - double rotZ = 2 * r1 - 1; - double rotX = Math.Sqrt(1 - rotZ * rotZ) * Math.Sin(r2); - double rotY = Math.Sqrt(1 - rotZ * rotZ) * Math.Cos(r2); - - double angle = r3 * directionalDensity + directionalDensity * 0.1; //Statistics.NormalDistribution(0, directionalDensity); - - double cos = Math.Cos(angle); - double sin = Math.Sin(angle); - double oneMinusCos = 1 - cos; - - double nxyc = rotX * rotY * oneMinusCos; - double nyzc = rotY * rotZ * oneMinusCos; - double nzxc = rotZ * rotX * oneMinusCos; - double nxs = rotX * sin; - double nys = rotY * sin; - double nzs = rotZ * sin; - - Matrix3D m = new Matrix3D( - oneMinusCos * rotX * rotX + cos, nxyc + nzs, nzxc - nys, - nxyc - nzs, oneMinusCos * rotY * rotY + cos, nyzc + nxs, - nzxc + nys, nyzc - nxs, oneMinusCos * rotZ * rotZ + cos); - - mat[i] = m * seed; - }); - return mat; + } } + GC.Collect(); + */ + } + + #region お蔵入り中 + /* + public static object lockObject = new object(); + private static Random rn = new Random(); - - public static Matrix3D[] GenerateRandomOrientation(int number) + /// + /// + /// + /// + /// + /// + /// + public static Matrix3D[] GenerateBiasedOrientation(Matrix3D seed, int number, double directionalDensity) + { + Matrix3D[] mat = new Matrix3D[number]; + ParallelOptions p = new ParallelOptions(); + p.MaxDegreeOfParallelism = Environment.ProcessorCount; + Parallel.For(0, number, p, i => { - Matrix3D[] mat = new Matrix3D[number]; - for (int i = 0; i < number; i++) + double r1, r2, r3; + lock (lockObject) { - mat[i] = Matrix3D.GenerateRamdomRotationMatrix(); + r1 = rn.NextDouble(); + r2 = rn.NextDouble() * 2 * Math.PI; + r3 = rn.NextDouble(); } - return mat; + double rotZ = 2 * r1 - 1; + double rotX = Math.Sqrt(1 - rotZ * rotZ) * Math.Sin(r2); + double rotY = Math.Sqrt(1 - rotZ * rotZ) * Math.Cos(r2); + + double angle = r3 * directionalDensity + directionalDensity * 0.1; //Statistics.NormalDistribution(0, directionalDensity); + + double cos = Math.Cos(angle); + double sin = Math.Sin(angle); + double oneMinusCos = 1 - cos; + + double nxyc = rotX * rotY * oneMinusCos; + double nyzc = rotY * rotZ * oneMinusCos; + double nzxc = rotZ * rotX * oneMinusCos; + double nxs = rotX * sin; + double nys = rotY * sin; + double nzs = rotZ * sin; + + Matrix3D m = new Matrix3D( + oneMinusCos * rotX * rotX + cos, nxyc + nzs, nzxc - nys, + nxyc - nzs, oneMinusCos * rotY * rotY + cos, nyzc + nxs, + nzxc + nys, nyzc - nxs, oneMinusCos * rotZ * rotZ + cos); + + mat[i] = m * seed; + }); + return mat; + } + + + public static Matrix3D[] GenerateRandomOrientation(int number) + { + Matrix3D[] mat = new Matrix3D[number]; + for (int i = 0; i < number; i++) + { + mat[i] = Matrix3D.GenerateRamdomRotationMatrix(); } - */ - #endregion お蔵入り中 + return mat; + } + */ + #endregion お蔵入り中 - /// - /// 近い方位を計算するためのプライベート変数 - /// - private Vector3DBase[][][] vec; + /// + /// 近い方位を計算するためのプライベート変数 + /// + private Vector3DBase[][][] vec; - private void initializeVec() + private void initializeVec() + { + Vector3DBase v = new Vector3DBase(0, 0, 1); + vec = new Vector3DBase[6][][]; + for (int plane = 0; plane < 6; plane++) { - Vector3DBase v = new Vector3DBase(0, 0, 1); - vec = new Vector3DBase[6][][]; - for (int plane = 0; plane < 6; plane++) + vec[plane] = new Vector3DBase[SquareDiv][]; + for (int y = 0; y < SquareDiv; y++) { - vec[plane] = new Vector3DBase[SquareDiv][]; - for (int y = 0; y < SquareDiv; y++) - { - vec[plane][y] = new Vector3DBase[SquareDiv]; - for (int x = 0; x < SquareDiv; x++) - vec[plane][y][x] = Rotations[GetIndex(plane, x, y, 0)] * v; - } + vec[plane][y] = new Vector3DBase[SquareDiv]; + for (int x = 0; x < SquareDiv; x++) + vec[plane][y][x] = Rotations[GetIndex(plane, x, y, 0)] * v; } } + } - /// - /// n番目の結晶子に近い方位を計算し、指定された密度で返す - /// - /// - /// - public void GetBiasedDirection(int n, ref int[] densityIndex, ref double[] densityValue, double range, double ratio) - { - if (vec == null || vec[0].Length != SquareDiv) - initializeVec(); + /// + /// n番目の結晶子に近い方位を計算し、指定された密度で返す + /// + /// + /// + public void GetBiasedDirection(int n, ref int[] densityIndex, ref double[] densityValue, double range, double ratio) + { + if (vec == null || vec[0].Length != SquareDiv) + initializeVec(); - Matrix3D baseRotation = Rotations[n].Inverse(); - double thresholdMax = Math.Cos(range * 3); - double threshold = 1 + 2 * Math.Cos(range * 2); + Matrix3D baseRotation = Rotations[n].Inverse(); + double thresholdMax = Math.Cos(range * 3); + double threshold = 1 + 2 * Math.Cos(range * 2); - List[] key = new List[SquareDiv]; - List[] value = new List[SquareDiv]; + List[] key = new List[SquareDiv]; + List[] value = new List[SquareDiv]; - //まず、n番目のplane,x,y,rotを取得 - int basePlane = 0, baseX = 0, baseY = 0, baseRot = 0; - GetIndex(n, ref basePlane, ref baseX, ref baseY, ref baseRot); + //まず、n番目のplane,x,y,rotを取得 + int basePlane = 0, baseX = 0, baseY = 0, baseRot = 0; + GetIndex(n, ref basePlane, ref baseX, ref baseY, ref baseRot); - //次に、rotを固定して、すべてのplane, x, yの行列を計算する - Parallel.For(0, SquareDiv, y => - { - key[y] = new List(); - value[y] = new List(); - for (int plane = 0; plane < 6; plane++) - for (int x = 0; x < SquareDiv; x++) - { - if (vec[basePlane][baseY][baseX] * vec[plane][y][x] > thresholdMax) - for (int rot = 0; rot < RotationDiv; rot++) + //次に、rotを固定して、すべてのplane, x, yの行列を計算する + Parallel.For(0, SquareDiv, y => + { + key[y] = new List(); + value[y] = new List(); + for (int plane = 0; plane < 6; plane++) + for (int x = 0; x < SquareDiv; x++) + { + if (vec[basePlane][baseY][baseX] * vec[plane][y][x] > thresholdMax) + for (int rot = 0; rot < RotationDiv; rot++) + { + Matrix3D m = Rotations[GetIndex(plane, x, y, rot)]; + double a = m.E11 * baseRotation.E11 + m.E12 * baseRotation.E21 + m.E13 * baseRotation.E31 + + m.E21 * baseRotation.E12 + m.E22 * baseRotation.E22 + m.E23 * baseRotation.E32 + + m.E31 * baseRotation.E13 + m.E32 * baseRotation.E23 + m.E33 * baseRotation.E33; + if (a > threshold) { - Matrix3D m = Rotations[GetIndex(plane, x, y, rot)]; - double a = m.E11 * baseRotation.E11 + m.E12 * baseRotation.E21 + m.E13 * baseRotation.E31 - + m.E21 * baseRotation.E12 + m.E22 * baseRotation.E22 + m.E23 * baseRotation.E32 - + m.E31 * baseRotation.E13 + m.E32 * baseRotation.E23 + m.E33 * baseRotation.E33; - if (a > threshold) - { - double d = Math.Acos(Math.Min(1.0, (a - 1.0) / 2.0)) / range; - key[y].Add(GetIndex(plane, x, y, rot)); - value[y].Add(1 / (1 + d * d)); - } + double d = Math.Acos(Math.Min(1.0, (a - 1.0) / 2.0)) / range; + key[y].Add(GetIndex(plane, x, y, rot)); + value[y].Add(1 / (1 + d * d)); } - } - }); + } + } + }); - for (int i = 1; i < key.Length; i++) - { - key[0].AddRange(key[i]); - value[0].AddRange(value[i]); - } - double sum = value[0].Sum(); - if (sum > 0) - { - for (int i = 0; i < value[0].Count; i++) - value[0][i] *= ratio * TotalCrystalline / sum; - densityIndex = key[0].ToArray(); - densityValue = value[0].ToArray(); - } - else - { - densityIndex = new int[] { 0 }; - densityValue = new double[] { 0 }; - } + for (int i = 1; i < key.Length; i++) + { + key[0].AddRange(key[i]); + value[0].AddRange(value[i]); } - - /// - /// 通し番号n から、面番号planeやxy座標を返す - /// - /// - /// - /// - /// - /// - public void GetIndex(int n, ref int plane, ref int x, ref int y, ref int rot) + double sum = value[0].Sum(); + if (sum > 0) { - plane = n / (TotalCrystalline / 6); //0~5 - n -= plane * TotalCrystalline / 6; - rot = n % RotationDiv; - n /= RotationDiv; - x = n % SquareDiv; - y = n / SquareDiv; + for (int i = 0; i < value[0].Count; i++) + value[0][i] *= ratio * TotalCrystalline / sum; + densityIndex = key[0].ToArray(); + densityValue = value[0].ToArray(); } - - public int GetIndex(int plane, int x, int y, int rot) + else { - return plane * SquareDiv * SquareDiv * RotationDiv + y * SquareDiv * RotationDiv + x * RotationDiv + rot; + densityIndex = new int[] { 0 }; + densityValue = new double[] { 0 }; } + } - /// - /// 指定した角度分解能で、全球を分割し、角度情報をRotations, SubRotationsに格納 - /// - public void setCrystallineRotation() - { + /// + /// 通し番号n から、面番号planeやxy座標を返す + /// + /// + /// + /// + /// + /// + public void GetIndex(int n, ref int plane, ref int x, ref int y, ref int rot) + { + plane = n / (TotalCrystalline / 6); //0~5 + n -= plane * TotalCrystalline / 6; + rot = n % RotationDiv; + n /= RotationDiv; + x = n % SquareDiv; + y = n / SquareDiv; + } - Rotations1 = new Matrix3D[SquareDiv * SquareDiv]; - Parallel.For(0, SquareDiv, y => - { - double b = Math.Tan(((y + 0.5) / SquareDiv - 0.5) * Math.PI / 2); - for (int x = 0; x < SquareDiv; x++) - { - double a = Math.Tan(((x + 0.5) / SquareDiv - 0.5) * Math.PI / 2); - double norm = Math.Sqrt(a * a + b * b + 1); - double u = a / norm, v = b / norm; - double cosTheta = 1 / norm, sinTheta = Math.Sqrt(1 - cosTheta * cosTheta); - double cosPhi = u / sinTheta, sinPhi = v / sinTheta; - if (sinTheta == 0) - { cosPhi = 1; sinPhi = 0; } - Rotations1[y * SquareDiv + x] = new Matrix3D(cosPhi, -sinPhi, 0, sinPhi, cosPhi, 0, 0, 0, 1) * new Matrix3D(1, 0, 0, 0, cosTheta, sinTheta, 0, -sinTheta, cosTheta); - } - }); + public int GetIndex(int plane, int x, int y, int rot) + { + return plane * SquareDiv * SquareDiv * RotationDiv + y * SquareDiv * RotationDiv + x * RotationDiv + rot; + } + + /// + /// 指定した角度分解能で、全球を分割し、角度情報をRotations, SubRotationsに格納 + /// + public void setCrystallineRotation() + { - Rotations2 = new Matrix3D[RotationDiv]; - for (int rot = 0; rot < RotationDiv; rot++) + Rotations1 = new Matrix3D[SquareDiv * SquareDiv]; + Parallel.For(0, SquareDiv, y => + { + double b = Math.Tan(((y + 0.5) / SquareDiv - 0.5) * Math.PI / 2); + for (int x = 0; x < SquareDiv; x++) { - double cosKsi = Math.Cos(2 * Math.PI * rot / RotationDiv), sinKsi = Math.Sin(2 * Math.PI * rot / RotationDiv); - Rotations2[rot] = new Matrix3D(cosKsi, -sinKsi, 0, sinKsi, cosKsi, 0, 0, 0, 1); + double a = Math.Tan(((x + 0.5) / SquareDiv - 0.5) * Math.PI / 2); + double norm = Math.Sqrt(a * a + b * b + 1); + double u = a / norm, v = b / norm; + double cosTheta = 1 / norm, sinTheta = Math.Sqrt(1 - cosTheta * cosTheta); + double cosPhi = u / sinTheta, sinPhi = v / sinTheta; + if (sinTheta == 0) + { cosPhi = 1; sinPhi = 0; } + Rotations1[y * SquareDiv + x] = new Matrix3D(cosPhi, -sinPhi, 0, sinPhi, cosPhi, 0, 0, 0, 1) * new Matrix3D(1, 0, 0, 0, cosTheta, sinTheta, 0, -sinTheta, cosTheta); } + }); + Rotations2 = new Matrix3D[RotationDiv]; + for (int rot = 0; rot < RotationDiv; rot++) + { + double cosKsi = Math.Cos(2 * Math.PI * rot / RotationDiv), sinKsi = Math.Sin(2 * Math.PI * rot / RotationDiv); + Rotations2[rot] = new Matrix3D(cosKsi, -sinKsi, 0, sinKsi, cosKsi, 0, 0, 0, 1); + } - Rotations = new Matrix3D[TotalCrystalline]; - int m = SquareDiv * SquareDiv * RotationDiv; - Parallel.For(0, Rotations1.Length, i => - { - for (int j = 0; j < Rotations2.Length; j++) - { - var mat = Rotations1[i] * Rotations2[j]; - int baseIndex = i * RotationDiv + j; - for (int plane = 0; plane < 6; plane++) - Rotations[plane * m + baseIndex] = ConvertRotationByPlane(mat, plane); - } - }); - SubRot1 = new Matrix3D[BaseCrystal.SubDivision * BaseCrystal.SubDivision * SquareDiv * SquareDiv]; - Parallel.For(0, SquareDiv * BaseCrystal.SubDivision, y => + Rotations = new Matrix3D[TotalCrystalline]; + int m = SquareDiv * SquareDiv * RotationDiv; + Parallel.For(0, Rotations1.Length, i => + { + for (int j = 0; j < Rotations2.Length; j++) { - double b = Math.Tan(((y + 0.5) / SquareDiv / BaseCrystal.SubDivision - 0.5) * Math.PI / 2); + var mat = Rotations1[i] * Rotations2[j]; + int baseIndex = i * RotationDiv + j; + for (int plane = 0; plane < 6; plane++) + Rotations[plane * m + baseIndex] = ConvertRotationByPlane(mat, plane); + } + }); - for (int x = 0; x < SquareDiv * BaseCrystal.SubDivision; x++) - { - double a = Math.Tan(((x + 0.5) / SquareDiv / BaseCrystal.SubDivision - 0.5) * Math.PI / 2); - double norm = Math.Sqrt(a * a + b * b + 1); - double u = a / norm, v = b / norm; - double cosTheta = 1 / norm, sinTheta = Math.Sqrt(1 - cosTheta * cosTheta); - double cosPhi = u / sinTheta, sinPhi = v / sinTheta; - if (sinTheta == 0) - { cosPhi = 1; sinPhi = 0; } - SubRot1[y * SquareDiv * BaseCrystal.SubDivision + x] - = new Matrix3D(cosPhi, -sinPhi, 0, sinPhi, cosPhi, 0, 0, 0, 1) * new Matrix3D(1, 0, 0, 0, cosTheta, sinTheta, 0, -sinTheta, cosTheta); - } - }); + SubRot1 = new Matrix3D[BaseCrystal.SubDivision * BaseCrystal.SubDivision * SquareDiv * SquareDiv]; + Parallel.For(0, SquareDiv * BaseCrystal.SubDivision, y => + { + double b = Math.Tan(((y + 0.5) / SquareDiv / BaseCrystal.SubDivision - 0.5) * Math.PI / 2); - SubRot2 = new Matrix3D[BaseCrystal.SubDivision * RotationDiv]; - for (int rot = 0; rot < RotationDiv * BaseCrystal.SubDivision; rot++) + for (int x = 0; x < SquareDiv * BaseCrystal.SubDivision; x++) { - double cosKsi = Math.Cos(2 * Math.PI * rot / RotationDiv / SubDiv), sinKsi = Math.Sin(2 * Math.PI * rot / RotationDiv / SubDiv); - SubRot2[rot] = new Matrix3D(cosKsi, -sinKsi, 0, sinKsi, cosKsi, 0, 0, 0, 1); + double a = Math.Tan(((x + 0.5) / SquareDiv / BaseCrystal.SubDivision - 0.5) * Math.PI / 2); + double norm = Math.Sqrt(a * a + b * b + 1); + double u = a / norm, v = b / norm; + double cosTheta = 1 / norm, sinTheta = Math.Sqrt(1 - cosTheta * cosTheta); + double cosPhi = u / sinTheta, sinPhi = v / sinTheta; + if (sinTheta == 0) + { cosPhi = 1; sinPhi = 0; } + SubRot1[y * SquareDiv * BaseCrystal.SubDivision + x] + = new Matrix3D(cosPhi, -sinPhi, 0, sinPhi, cosPhi, 0, 0, 0, 1) * new Matrix3D(1, 0, 0, 0, cosTheta, sinTheta, 0, -sinTheta, cosTheta); } - } - - //private Matrix3D rotationX = Matrix3D.Rot(new Vector3DBase(1, 0, 0), Math.PI); - //private Matrix3D rotationY = Matrix3D.Rot(new Vector3DBase(0, 1, 0), Math.PI); - //private Matrix3D rotationZ = Matrix3D.Rot(new Vector3DBase(0, 0, 1), Math.PI); - - public static Matrix3D ConvertRotationByPlane(Matrix3D m, int plane) => plane switch - { - 1 => m.ExchangeYZX(), - 2 => m.ExchangeZXY(), - 3 => m.ExchangeX_Y_Z(), - 4 => m.ExchangeY_Z_X(), - 5 => m.ExchangeZ_X_Y(), - _ => m, - }; - - /// - /// あるplane,x,y,rotに属するSubRotations配列を返す。あらかじめsetCrystallineRotation()で初期化しておく必要がある - /// - /// - /// - /// - /// - /// - private Matrix3D[] getSubRotations(int plane, int x, int y, int rot) - { - var m = new Matrix3D[SubDiv * SubDiv * SubDiv]; - for (int i = 0, n = 0; i < SubDiv; i++) - for (int j = 0; j < SubDiv; j++) - for (int k = 0; k < SubDiv; k++) - m[n++] = ConvertRotationByPlane(SubRot1[SubDiv * SubDiv * SquareDiv * y + SubDiv * x + SubDiv * SquareDiv * i + j] * SubRot2[SubDiv * rot + k], plane); - return m; - } + }); - /// - /// あるplane,x,y,rotに属するSubRotations配列を返す。あらかじめsetCrystallineRotation()で初期化しておく必要がある - /// - /// - /// - /// - /// - /// - private Matrix3D[] getSubRotations(int num) + SubRot2 = new Matrix3D[BaseCrystal.SubDivision * RotationDiv]; + for (int rot = 0; rot < RotationDiv * BaseCrystal.SubDivision; rot++) { - int plane = num / (TotalCrystalline / 6); //0~5 - num -= plane * TotalCrystalline / 6; - int rot = num % RotationDiv; - num /= RotationDiv; - int x = num % SquareDiv; - int y = num / SquareDiv; - return getSubRotations(plane, x, y, rot); + double cosKsi = Math.Cos(2 * Math.PI * rot / RotationDiv / SubDiv), sinKsi = Math.Sin(2 * Math.PI * rot / RotationDiv / SubDiv); + SubRot2[rot] = new Matrix3D(cosKsi, -sinKsi, 0, sinKsi, cosKsi, 0, 0, 0, 1); } + } - /// - /// ある角度範囲が受け持つ立体角を初期化 - /// - private void setCrystallineSolidAngle() - { - SolidAngle = new double[TotalCrystalline]; + //private Matrix3D rotationX = Matrix3D.Rot(new Vector3DBase(1, 0, 0), Math.PI); + //private Matrix3D rotationY = Matrix3D.Rot(new Vector3DBase(0, 1, 0), Math.PI); + //private Matrix3D rotationZ = Matrix3D.Rot(new Vector3DBase(0, 0, 1), Math.PI); - Parallel.For(0, SquareDiv, y => - { - for (int x = 0; x < SquareDiv; x++) - { - var pt = new List(); - for (double i = 0; i < 2; i++) - for (double j = 0; j < 2; j++) - { - var a = Math.Tan(((x + i) / SquareDiv - 0.5) * Math.PI / 2); - var b = Math.Tan(((y + j) / SquareDiv - 0.5) * Math.PI / 2); - pt.Add(Stereonet.ConvertVectorToSchmidt(new Vector3D(a, b, 1)) * 10); - } - var area = Geometriy.GetPolygonalArea(new[] { pt[0], pt[1], pt[3], pt[2] }); - for (int plane = 0; plane < 6; plane++) - for (int rot = 0; rot < RotationDiv; rot++) - SolidAngle[plane * SquareDiv * SquareDiv * RotationDiv + y * SquareDiv * RotationDiv + x * RotationDiv + rot] = area; - } - }); - } - - /// - /// 各Crystallineの回折が寄与するピクセルのindexと指数を計算し、PixelIndexとPixelIntensityに格納する - /// - /// AreaDetectorクラスの情報を与える - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void SetDiffractedPixels(AreaDetector detector) - { - stopwatch.Restart(); - BaseCrystal.ElasticStiffness[0, 0] = BaseCrystal.ElasticStiffness[1, 1] = 1350; - BaseCrystal.ElasticStiffness[2, 2] = 1310; - BaseCrystal.ElasticStiffness[3, 3] = BaseCrystal.ElasticStiffness[4, 4] = 400; - BaseCrystal.ElasticStiffness[5, 5] = 230; - BaseCrystal.ElasticStiffness[0, 1] = BaseCrystal.ElasticStiffness[1, 0] = 890; - BaseCrystal.ElasticStiffness[0, 2] = BaseCrystal.ElasticStiffness[2, 0] = 900; - BaseCrystal.ElasticStiffness[1, 2] = BaseCrystal.ElasticStiffness[2, 1] = 900; - - var elasticity = new Elasticity(DenseMatrix.OfArray(BaseCrystal.ElasticStiffness), Elasticity.Mode.Stiffness); - - BaseCrystal.Stress.E11 = -10; - BaseCrystal.Stress.E22 = 5; - BaseCrystal.Stress.E33 = 5; - BaseCrystal.Strain.E11 = 0; - BaseCrystal.Strain.E22 = 0; - BaseCrystal.Strain.E33 = 0; - BaseCrystal.HillCoefficient = 1; - - bool strainFree = BaseCrystal.Stress.IsZero() && BaseCrystal.Strain.IsZero(); - bool rotationFree = WholeRotation.IsIdentity(); - double ewaldR = 1 / detector.WaveLength, ewaldR2 = ewaldR * ewaldR; - double monochromaticity2 = detector.Monochromaticity * detector.Monochromaticity; - double maxMonochroHK2 = 2 * detector.MaxReciproZ * ewaldR * monochromaticity2; //Z - double reciprocalPointSize = 1 / GrainSize / 2, reciprocalPointSize2 = reciprocalPointSize * reciprocalPointSize; + public static Matrix3D ConvertRotationByPlane(Matrix3D m, int plane) => plane switch + { + 1 => m.ExchangeYZX(), + 2 => m.ExchangeZXY(), + 3 => m.ExchangeX_Y_Z(), + 4 => m.ExchangeY_Z_X(), + 5 => m.ExchangeZ_X_Y(), + _ => m, + }; - var subDiv3 = SubDiv * SubDiv * SubDiv; + /// + /// あるplane,x,y,rotに属するSubRotations配列を返す。あらかじめsetCrystallineRotation()で初期化しておく必要がある + /// + /// + /// + /// + /// + /// + private Matrix3D[] getSubRotations(int plane, int x, int y, int rot) + { + var m = new Matrix3D[SubDiv * SubDiv * SubDiv]; + for (int i = 0, n = 0; i < SubDiv; i++) + for (int j = 0; j < SubDiv; j++) + for (int k = 0; k < SubDiv; k++) + m[n++] = ConvertRotationByPlane(SubRot1[SubDiv * SubDiv * SquareDiv * y + SubDiv * x + SubDiv * SquareDiv * i + j] * SubRot2[SubDiv * rot + k], plane); + return m; + } - var maxConvergenceHK = Math.Sin(BaseCrystal.AngleResolution / 180.0 * Math.PI / 2) / detector.WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸垂直な方向) - if (SubDiv == 1) - maxConvergenceHK = Math.Sin(detector.Convergence / 2) / detector.WaveLength; - var maxConvergenceHK2 = maxConvergenceHK * maxConvergenceHK; - double maxExcitationError2 = reciprocalPointSize2 + maxMonochroHK2 + maxConvergenceHK2, maxExcitationError = Math.Sqrt(maxExcitationError2); - var maxHk2square = reciprocalPointSize2 + maxConvergenceHK2; // (-y,x,0)方向の半値幅 + /// + /// あるplane,x,y,rotに属するSubRotations配列を返す。あらかじめsetCrystallineRotation()で初期化しておく必要がある + /// + /// + /// + /// + /// + /// + private Matrix3D[] getSubRotations(int num) + { + int plane = num / (TotalCrystalline / 6); //0~5 + num -= plane * TotalCrystalline / 6; + int rot = num % RotationDiv; + num /= RotationDiv; + int x = num % SquareDiv; + int y = num / SquareDiv; + return getSubRotations(plane, x, y, rot); + } - var camPerRes = detector.CameraLength / detector.Resolution; - double cX = detector.Center.X, cY = detector.Center.Y; - int imageWidth = detector.ImageWidth, imageHeight = detector.ImageHeight; - uint imageLength = (uint)detector.ImageLength; + /// + /// ある角度範囲が受け持つ立体角を初期化 + /// + private void setCrystallineSolidAngle() + { + SolidAngle = new double[TotalCrystalline]; - if (ValidIndex == null) - ValidIndex = new int[TotalCrystalline][]; - Pixel = new (int Index, double Intensity)[TotalCrystalline][]; + Parallel.For(0, SquareDiv, y => + { + for (int x = 0; x < SquareDiv; x++) + { + var pt = new List(); + for (double i = 0; i < 2; i++) + for (double j = 0; j < 2; j++) + { + var a = Math.Tan(((x + i) / SquareDiv - 0.5) * Math.PI / 2); + var b = Math.Tan(((y + j) / SquareDiv - 0.5) * Math.PI / 2); + pt.Add(Stereonet.ConvertVectorToSchmidt(new Vector3D(a, b, 1)) * 10); + } + var area = Geometry.GetPolygonalArea(new[] { pt[0], pt[1], pt[3], pt[2] }); + for (int plane = 0; plane < 6; plane++) + for (int rot = 0; rot < RotationDiv; rot++) + SolidAngle[plane * SquareDiv * SquareDiv * RotationDiv + y * SquareDiv * RotationDiv + x * RotationDiv + rot] = area; + } + }); + } - #region エワルド球に近い(回折条件に引っ掛かる)逆格子ベクトルを探索するローカル関数 - int[] searchValidIndex(int num) + /// + /// 各Crystallineの回折が寄与するピクセルのindexと指数を計算し、PixelIndexとPixelIntensityに格納する + /// + /// AreaDetectorクラスの情報を与える + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetDiffractedPixels(AreaDetector detector) + { + stopwatch.Restart(); + BaseCrystal.ElasticStiffness[0, 0] = BaseCrystal.ElasticStiffness[1, 1] = 1350; + BaseCrystal.ElasticStiffness[2, 2] = 1310; + BaseCrystal.ElasticStiffness[3, 3] = BaseCrystal.ElasticStiffness[4, 4] = 400; + BaseCrystal.ElasticStiffness[5, 5] = 230; + BaseCrystal.ElasticStiffness[0, 1] = BaseCrystal.ElasticStiffness[1, 0] = 890; + BaseCrystal.ElasticStiffness[0, 2] = BaseCrystal.ElasticStiffness[2, 0] = 900; + BaseCrystal.ElasticStiffness[1, 2] = BaseCrystal.ElasticStiffness[2, 1] = 900; + + var elasticity = new Elasticity(DenseMatrix.OfArray(BaseCrystal.ElasticStiffness), Elasticity.Mode.Stiffness); + + BaseCrystal.Stress.E11 = -10; + BaseCrystal.Stress.E22 = 5; + BaseCrystal.Stress.E33 = 5; + BaseCrystal.Strain.E11 = 0; + BaseCrystal.Strain.E22 = 0; + BaseCrystal.Strain.E33 = 0; + BaseCrystal.HillCoefficient = 1; + + bool strainFree = BaseCrystal.Stress.IsZero() && BaseCrystal.Strain.IsZero(); + bool rotationFree = WholeRotation.IsIdentity(); + double ewaldR = 1 / detector.WaveLength, ewaldR2 = ewaldR * ewaldR; + double monochromaticity2 = detector.Monochromaticity * detector.Monochromaticity; + double maxMonochroHK2 = 2 * detector.MaxReciproZ * ewaldR * monochromaticity2; //Z + double reciprocalPointSize = 1 / GrainSize / 2, reciprocalPointSize2 = reciprocalPointSize * reciprocalPointSize; + + var subDiv3 = SubDiv * SubDiv * SubDiv; + + var maxConvergenceHK = Math.Sin(BaseCrystal.AngleResolution / 180.0 * Math.PI / 2) / detector.WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸垂直な方向) + if (SubDiv == 1) + maxConvergenceHK = Math.Sin(detector.Convergence / 2) / detector.WaveLength; + var maxConvergenceHK2 = maxConvergenceHK * maxConvergenceHK; + double maxExcitationError2 = reciprocalPointSize2 + maxMonochroHK2 + maxConvergenceHK2, maxExcitationError = Math.Sqrt(maxExcitationError2); + var maxHk2square = reciprocalPointSize2 + maxConvergenceHK2; // (-y,x,0)方向の半値幅 + + var camPerRes = detector.CameraLength / detector.Resolution; + double cX = detector.Center.X, cY = detector.Center.Y; + int imageWidth = detector.ImageWidth, imageHeight = detector.ImageHeight; + uint imageLength = (uint)detector.ImageLength; + + if (ValidIndex == null) + ValidIndex = new int[TotalCrystalline][]; + Pixel = new (int Index, double Intensity)[TotalCrystalline][]; + + #region エワルド球に近い(回折条件に引っ掛かる)逆格子ベクトルを探索するローカル関数 + int[] searchValidIndex(int num) + { + var baseRot = new Matrix3D(Rotations[num]); + if (!strainFree) baseRot = (elasticity.GetStrainByHill(BaseCrystal.Symmetry, baseRot, BaseCrystal.Stress, BaseCrystal.Strain, BaseCrystal.HillCoefficient) + new Matrix3D()).Inverse() * baseRot; + if (!rotationFree) baseRot = WholeRotation * baseRot; + var rot = baseRot.ToArrayRowMajorOrder(); + var result = new List(); + for (int n = 0; n < G.Length; n++) { - var baseRot = new Matrix3D(Rotations[num]); - if (!strainFree) baseRot = (elasticity.GetStrainByHill(BaseCrystal.Symmetry, baseRot, BaseCrystal.Stress, BaseCrystal.Strain, BaseCrystal.HillCoefficient) + new Matrix3D()).Inverse() * baseRot; - if (!rotationFree) baseRot = WholeRotation * baseRot; - var rot = baseRot.ToArrayRowMajorOrder(); - var result = new List(); - for (int n = 0; n < G.Length; n++) + var Z = rot[6] * G[n].X + rot[7] * G[n].Y + rot[8] * G[n].Z; + if (Z > -maxExcitationError * 2 && detector.MaxReciproZ + maxExcitationError * 2 > Z) { - var Z = rot[6] * G[n].X + rot[7] * G[n].Y + rot[8] * G[n].Z; - if (Z > -maxExcitationError * 2 && detector.MaxReciproZ + maxExcitationError * 2 > Z) - { - var X = rot[0] * G[n].X + rot[1] * G[n].Y + rot[2] * G[n].Z; - var Y = rot[3] * G[n].X + rot[4] * G[n].Y + rot[5] * G[n].Z; + var X = rot[0] * G[n].X + rot[1] * G[n].Y + rot[2] * G[n].Z; + var Y = rot[3] * G[n].X + rot[4] * G[n].Y + rot[5] * G[n].Z; - double rz = ewaldR - Z, rz2 = rz * rz; - double ptX = camPerRes / rz * X + cX; - double ptY = -camPerRes / rz * Y + cY; - if (ptX < imageWidth - 1 && ptX > 0 && ptY < imageHeight - 1 && ptY > 0) - { - //エワルド球面が、試料近傍で平面近似できるとして計算する 楕円(x-X)^2/hk1^2 + (z-Z)^2/hk3^2 == 1 と 直線 y = X/(R-Z) x + R(1-sqrt(X^2/(R-Z)^2+1)) の連立方程式を解く - var xyLength2 = X * X + Y * Y; - var hk1square = maxHk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 - var hk3square = reciprocalPointSize2 + monochromaticity2 * Z * Z;// (0,0,z)方向の半値幅 - var hk3per1 = hk3square / hk1square; - var sqrt = Math.Sqrt(1 + xyLength2 / rz2); - var a = hk3per1 + xyLength2 / rz2; - var b2 = (hk3per1 + (ewaldR * sqrt - ewaldR + Z) / rz) * (hk3per1 + (ewaldR * sqrt - ewaldR + Z) / rz) * xyLength2; - var c = -hk3square * 4 + 2 * ewaldR * (ewaldR - rz * sqrt - Z) + hk3per1 * xyLength2 + ewaldR2 * xyLength2 / rz2 + Z * Z;//最初の項hk3へ書ける数値が許容半値幅の二乗 - if (b2 - a * c >= 0) - result.Add(n); - } + double rz = ewaldR - Z, rz2 = rz * rz; + double ptX = camPerRes / rz * X + cX; + double ptY = -camPerRes / rz * Y + cY; + if (ptX < imageWidth - 1 && ptX > 0 && ptY < imageHeight - 1 && ptY > 0) + { + //エワルド球面が、試料近傍で平面近似できるとして計算する 楕円(x-X)^2/hk1^2 + (z-Z)^2/hk3^2 == 1 と 直線 y = X/(R-Z) x + R(1-sqrt(X^2/(R-Z)^2+1)) の連立方程式を解く + var xyLength2 = X * X + Y * Y; + var hk1square = maxHk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 + var hk3square = reciprocalPointSize2 + monochromaticity2 * Z * Z;// (0,0,z)方向の半値幅 + var hk3per1 = hk3square / hk1square; + var sqrt = Math.Sqrt(1 + xyLength2 / rz2); + var a = hk3per1 + xyLength2 / rz2; + var b2 = (hk3per1 + (ewaldR * sqrt - ewaldR + Z) / rz) * (hk3per1 + (ewaldR * sqrt - ewaldR + Z) / rz) * xyLength2; + var c = -hk3square * 4 + 2 * ewaldR * (ewaldR - rz * sqrt - Z) + hk3per1 * xyLength2 + ewaldR2 * xyLength2 / rz2 + Z * Z;//最初の項hk3へ書ける数値が許容半値幅の二乗 + if (b2 - a * c >= 0) + result.Add(n); } } - return result.ToArray(); } - #endregion + return result.ToArray(); + } + #endregion - #region 逆格子ベクトルの回折位置・強度計算し,Pixelに格納するローカル関数 - double log2 = Math.Log(2), sqrtPiLog2 = Math.Sqrt(Math.PI * log2); - (int Index, double Intensity)[] calculatePixel(int num) - { - var rotations = getSubRotations(num); - if (!strainFree) - rotations = rotations.Select(r => - (elasticity.GetStrainByHill(BaseCrystal.Symmetry, r, BaseCrystal.Stress, BaseCrystal.Strain, BaseCrystal.HillCoefficient) + new Matrix3D()).Inverse() * r).ToArray(); + #region 逆格子ベクトルの回折位置・強度計算し,Pixelに格納するローカル関数 + double log2 = Math.Log(2), sqrtPiLog2 = Math.Sqrt(Math.PI * log2); + (int Index, double Intensity)[] calculatePixel(int num) + { + var rotations = getSubRotations(num); + if (!strainFree) + rotations = rotations.Select(r => + (elasticity.GetStrainByHill(BaseCrystal.Symmetry, r, BaseCrystal.Stress, BaseCrystal.Strain, BaseCrystal.HillCoefficient) + new Matrix3D()).Inverse() * r).ToArray(); - var result = new Dictionary(); + var result = new Dictionary(); - var rotArray = rotations.Select(r => r.ToArrayRowMajorOrder()).ToArray(); + var rotArray = rotations.Select(r => r.ToArrayRowMajorOrder()).ToArray(); - foreach (int gNum in ValidIndex[num]) + foreach (int gNum in ValidIndex[num]) + { + (var gX, var gY, var gZ, var Hk1, var Hk2, var Hk3, var Intensity, var Intensity2) = G[gNum]; + foreach (var rot in rotArray) { - (var gX, var gY, var gZ, var Hk1, var Hk2, var Hk3, var Intensity, var Intensity2) = G[gNum]; - foreach (var rot in rotArray) + var X = rot[0] * gX + rot[1] * gY + rot[2] * gZ; + var Y = rot[3] * gX + rot[4] * gY + rot[5] * gZ; + var Z = rot[6] * gX + rot[7] * gY + rot[8] * gZ; + double xyLength2 = X * X + Y * Y, xyLength = Math.Sqrt(xyLength2), rz = ewaldR - Z, rz2 = rz * rz; + //初期位置の計算 + var XY = (Hk3 / Hk1 + (ewaldR * Math.Sqrt(1 + xyLength2 / rz2) - ewaldR + Z) / rz) / (Hk3 / Hk1 + xyLength2 / rz2) * xyLength; + var d = camPerRes / Math.Sqrt(ewaldR2 / XY / XY - 1) / xyLength; + var startPosition = (int)(-d * Y + cY + 0.5) * imageWidth + (int)(d * X + cX + 0.5); + var tempIntensity = Intensity2 / subDiv3 * SolidAngle[num]; + + var angle = (int)((Math.Atan2(Y, X) / Math.PI + 1.0) * SpotShapesAngleDivision / 2); + foreach (var index in SpotShapesSortedIndex[gNum][angle]) //現在のピクセル位置から、周辺強度を計算していって、半値幅の2倍以上になったら終了 { - var X = rot[0] * gX + rot[1] * gY + rot[2] * gZ; - var Y = rot[3] * gX + rot[4] * gY + rot[5] * gZ; - var Z = rot[6] * gX + rot[7] * gY + rot[8] * gZ; - double xyLength2 = X * X + Y * Y, xyLength = Math.Sqrt(xyLength2), rz = ewaldR - Z, rz2 = rz * rz; - //初期位置の計算 - var XY = (Hk3 / Hk1 + (ewaldR * Math.Sqrt(1 + xyLength2 / rz2) - ewaldR + Z) / rz) / (Hk3 / Hk1 + xyLength2 / rz2) * xyLength; - var d = camPerRes / Math.Sqrt(ewaldR2 / XY / XY - 1) / xyLength; - var startPosition = (int)(-d * Y + cY + 0.5) * imageWidth + (int)(d * X + cX + 0.5); - var tempIntensity = Intensity2 / subDiv3 * SolidAngle[num]; - - var angle = (int)((Math.Atan2(Y, X) / Math.PI + 1.0) * SpotShapesAngleDivision / 2); - foreach (var index in SpotShapesSortedIndex[gNum][angle]) //現在のピクセル位置から、周辺強度を計算していって、半値幅の2倍以上になったら終了 + int pos = startPosition + index; + if ((uint)pos < imageLength) { - int pos = startPosition + index; - if ((uint)pos < imageLength) + var (vec, area) = detector.Reciprocal[pos]; + var temp1 = X * vec.X + Y * vec.Y - xyLength2; + var temp2 = X * vec.Y - Y * vec.X; + var temp3 = Z - vec.Z; + var dev2 = temp1 * temp1 / xyLength2 / Hk1 + temp2 * temp2 / xyLength2 / Hk2 + temp3 * temp3 / Hk3; + if (dev2 > DeviationThreshold[gNum] * 1.5) + break; + else if (dev2 < DeviationThreshold[gNum]) { - var (vec, area) = detector.Reciprocal[pos]; - var temp1 = X * vec.X + Y * vec.Y - xyLength2; - var temp2 = X * vec.Y - Y * vec.X; - var temp3 = Z - vec.Z; - var dev2 = temp1 * temp1 / xyLength2 / Hk1 + temp2 * temp2 / xyLength2 / Hk2 + temp3 * temp3 / Hk3; - if (dev2 > DeviationThreshold[gNum] * 1.5) - break; - else if (dev2 < DeviationThreshold[gNum]) - { - var temp = sqrtPiLog2 * Math.Exp(-log2 * dev2) * tempIntensity * area; + var temp = sqrtPiLog2 * Math.Exp(-log2 * dev2) * tempIntensity * area; - if (result.ContainsKey(pos)) - result[pos] += temp; - else - result.Add(pos, temp); - } + if (result.ContainsKey(pos)) + result[pos] += temp; + else + result.Add(pos, temp); } } } } - return result.Select(r => (r.Key, r.Value)).ToArray(); } - #endregion + return result.Select(r => (r.Key, r.Value)).ToArray(); + } + #endregion - var div = 100; - for (int i = 0; i < div; i++) - { - double ratio = (double)i / div, sec = stopwatch.ElapsedMilliseconds / 1000.0; - ProgressChanged?.Invoke(this, new ProgressChangedEventArgs((int)(100.0 * ratio), new object[] { ratio, $"Elapsed: {sec:f2}sec. Remaining: {sec * (1 - ratio) / ratio:f2}sec." })); + var div = 100; + for (int i = 0; i < div; i++) + { + double ratio = (double)i / div, sec = stopwatch.ElapsedMilliseconds / 1000.0; + ProgressChanged?.Invoke(this, new ProgressChangedEventArgs((int)(100.0 * ratio), new object[] { ratio, $"Elapsed: {sec:f2}sec. Remaining: {sec * (1 - ratio) / ratio:f2}sec." })); - Parallel.For(TotalCrystalline / div * i, Math.Min(TotalCrystalline, TotalCrystalline / div * (i + 1)), num => - //for(int num= TotalCrystalline / div * i; num< Math.Min(TotalCrystalline, TotalCrystalline / div * (i + 1)); i++) - { - if (ValidIndex[num] == null) - ValidIndex[num] = searchValidIndex(num); + Parallel.For(TotalCrystalline / div * i, Math.Min(TotalCrystalline, TotalCrystalline / div * (i + 1)), num => + //for(int num= TotalCrystalline / div * i; num< Math.Min(TotalCrystalline, TotalCrystalline / div * (i + 1)); i++) + { + if (ValidIndex[num] == null) + ValidIndex[num] = searchValidIndex(num); - if (ValidIndex[num].Length > 0) - Pixel[num] = calculatePixel(num); - }); - } + if (ValidIndex[num].Length > 0) + Pixel[num] = calculatePixel(num); + }); } + } - /// - /// SpotIDから呼ばれる。 - /// - /// - /// - /// - /// - public Vector3D[] GetSpotPosition(AreaDetector detector, Matrix3D m, bool calculateOnlySpotPositon = false) + /// + /// SpotIDから呼ばれる。 + /// + /// + /// + /// + /// + public Vector3D[] GetSpotPosition(AreaDetector detector, Matrix3D m, bool calculateOnlySpotPositon = false) + { + double ewaldR = 1 / detector.WaveLength, ewaldR2 = ewaldR * ewaldR; + double monochromaticity2 = detector.Monochromaticity * detector.Monochromaticity; + double maxMonochroHK2 = 2 * detector.MaxReciproZ * ewaldR * monochromaticity2; //Z + double size = GrainSize; + double reciprocalPointSize = 1 / size / 2, reciprocalPointSize2 = reciprocalPointSize * reciprocalPointSize; + + double maxConvergenceHK = Math.Sin(detector.Convergence / 2) / detector.WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸垂直な方向) + double maxConvergenceHK2 = maxConvergenceHK * maxConvergenceHK; + double maxExcitationError2 = reciprocalPointSize2 + maxMonochroHK2 + maxConvergenceHK2, maxExcitationError = Math.Sqrt(maxExcitationError2); + double maxHk2square = reciprocalPointSize2 + maxConvergenceHK2; // (-y,x,0)方向の半値幅 + + var list = new List(); + //エワルド球に近い(回折条件に引っ掛かる)逆格子ベクトルを探索 + for (int n = 0; n < G.Length; n++) { - double ewaldR = 1 / detector.WaveLength, ewaldR2 = ewaldR * ewaldR; - double monochromaticity2 = detector.Monochromaticity * detector.Monochromaticity; - double maxMonochroHK2 = 2 * detector.MaxReciproZ * ewaldR * monochromaticity2; //Z - double size = GrainSize; - double reciprocalPointSize = 1 / size / 2, reciprocalPointSize2 = reciprocalPointSize * reciprocalPointSize; - - double maxConvergenceHK = Math.Sin(detector.Convergence / 2) / detector.WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸垂直な方向) - double maxConvergenceHK2 = maxConvergenceHK * maxConvergenceHK; - double maxExcitationError2 = reciprocalPointSize2 + maxMonochroHK2 + maxConvergenceHK2, maxExcitationError = Math.Sqrt(maxExcitationError2); - double maxHk2square = reciprocalPointSize2 + maxConvergenceHK2; // (-y,x,0)方向の半値幅 - - var list = new List(); - //エワルド球に近い(回折条件に引っ掛かる)逆格子ベクトルを探索 - for (int n = 0; n < G.Length; n++) + double gX = G[n].X, gY = G[n].Y, gZ = G[n].Z; + double z = m.E31 * gX + m.E32 * gY + m.E33 * gZ; + if (z > -maxExcitationError * 2 && detector.MaxReciproZ + maxExcitationError * 2 > z) { - double gX = G[n].X, gY = G[n].Y, gZ = G[n].Z; - double z = m.E31 * gX + m.E32 * gY + m.E33 * gZ; - if (z > -maxExcitationError * 2 && detector.MaxReciproZ + maxExcitationError * 2 > z) + double rz = ewaldR - z; + double x = m.E11 * gX + m.E12 * gY + m.E13 * gZ; + double y = m.E21 * gX + m.E22 * gY + m.E23 * gZ; + double ptX = detector.CameraLength / detector.Resolution / rz * x + detector.Center.X; + double ptY = -detector.CameraLength / detector.Resolution / rz * y + detector.Center.Y; + if (ptX < detector.ImageWidth - 1 && ptX > 0 && ptY < detector.ImageHeight - 1 && ptY > 0) { - double rz = ewaldR - z; - double x = m.E11 * gX + m.E12 * gY + m.E13 * gZ; - double y = m.E21 * gX + m.E22 * gY + m.E23 * gZ; - double ptX = detector.CameraLength / detector.Resolution / rz * x + detector.Center.X; - double ptY = -detector.CameraLength / detector.Resolution / rz * y + detector.Center.Y; - if (ptX < detector.ImageWidth - 1 && ptX > 0 && ptY < detector.ImageHeight - 1 && ptY > 0) + //エワルド球面が、試料近傍で平面近似できるとして計算する 楕円(x-X)^2/hk1^2 + (z-Z)^2/hk3^2 == 1 と 直線 y = X/(R-Z) x + R(1-sqrt(X^2/(R-Z)^2+1)) の連立方程式を解く + double xyLength2 = x * x + y * y; + double hk1square = maxHk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 + double hk3square = reciprocalPointSize2 + monochromaticity2 * z * z;// (0,0,z)方向の半値幅 + double hk3per1 = hk3square / hk1square; + double sqrt = Math.Sqrt(1 + xyLength2 / rz / rz); + double a = hk3per1 + xyLength2 / rz / rz; + double b2 = (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * xyLength2; + double c = -hk3square * 4 + 2 * ewaldR * (ewaldR - rz * sqrt - z) + hk3per1 * xyLength2 + ewaldR2 * xyLength2 / rz / rz + z * z;//最初の項hk3へ書ける数値が許容半値幅の二乗 + if (b2 - a * c >= 0) { - //エワルド球面が、試料近傍で平面近似できるとして計算する 楕円(x-X)^2/hk1^2 + (z-Z)^2/hk3^2 == 1 と 直線 y = X/(R-Z) x + R(1-sqrt(X^2/(R-Z)^2+1)) の連立方程式を解く - double xyLength2 = x * x + y * y; - double hk1square = maxHk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 - double hk3square = reciprocalPointSize2 + monochromaticity2 * z * z;// (0,0,z)方向の半値幅 - double hk3per1 = hk3square / hk1square; - double sqrt = Math.Sqrt(1 + xyLength2 / rz / rz); - double a = hk3per1 + xyLength2 / rz / rz; - double b2 = (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * xyLength2; - double c = -hk3square * 4 + 2 * ewaldR * (ewaldR - rz * sqrt - z) + hk3per1 * xyLength2 + ewaldR2 * xyLength2 / rz / rz + z * z;//最初の項hk3へ書ける数値が許容半値幅の二乗 - if (b2 - a * c >= 0) - { - double xyLength = Math.Sqrt(xyLength2); - //初期位置の計算 - double XY = (G[n].Hk3 / G[n].Hk1 + (ewaldR * Math.Sqrt(1 + xyLength2 / rz / rz) - ewaldR + z) / rz) / (G[n].Hk3 / G[n].Hk1 + xyLength2 / rz / rz) * xyLength; - double d = detector.CameraLength / detector.Resolution / Math.Sqrt(ewaldR2 - XY * XY) / xyLength * XY; - double temp1 = x - x * ewaldR / rz / sqrt; - double temp3 = z - (-ewaldR / sqrt + ewaldR); - double dev2 = temp1 * temp1 / xyLength2 / G[n].Hk1 + temp3 * temp3 / G[n].Hk3; - double eta = 0; - double intensity = (eta / (1 + dev2) + (1 - eta) * Math.Sqrt(Math.PI * Math.Log(2)) * Math.Pow(2, -dev2)) * G[n].Intensity2; - - list.Add(new Vector3D(d * x + detector.Center.X, -d * y + detector.Center.Y, intensity)); - list[^1].Index = BaseCrystal.VectorOfG[n].Index; - } + double xyLength = Math.Sqrt(xyLength2); + //初期位置の計算 + double XY = (G[n].Hk3 / G[n].Hk1 + (ewaldR * Math.Sqrt(1 + xyLength2 / rz / rz) - ewaldR + z) / rz) / (G[n].Hk3 / G[n].Hk1 + xyLength2 / rz / rz) * xyLength; + double d = detector.CameraLength / detector.Resolution / Math.Sqrt(ewaldR2 - XY * XY) / xyLength * XY; + double temp1 = x - x * ewaldR / rz / sqrt; + double temp3 = z - (-ewaldR / sqrt + ewaldR); + double dev2 = temp1 * temp1 / xyLength2 / G[n].Hk1 + temp3 * temp3 / G[n].Hk3; + double eta = 0; + double intensity = (eta / (1 + dev2) + (1 - eta) * Math.Sqrt(Math.PI * Math.Log(2)) * Math.Pow(2, -dev2)) * G[n].Intensity2; + + list.Add(new Vector3D(d * x + detector.Center.X, -d * y + detector.Center.Y, intensity)); + list[^1].Index = BaseCrystal.VectorOfG[n].Index; } } - } //エワルド球に近い逆格子ベクトルを探索 ここまで - - return list.ToArray(); - } - - /// - /// 与えられた密度から、回折パターンを計算. - /// 予め、PixelIndexやPixelIntnsityをSetDiffractedPixels()で設定しておく必要があり。 - /// - /// - /// - /// - public double[] GetSimulatedPattern(AreaDetector detector, double[] density = null) - { - if (density == null) - density = Density; - - var pixels = new double[detector.ImageLength]; - for (int i = 0; i < TotalCrystalline; i++) - if (Pixel[i] != null) - foreach ((var Index, var Intensity) in Pixel[i]) - pixels[Index] += Intensity * density[i]; - return pixels; - } + } + } //エワルド球に近い逆格子ベクトルを探索 ここまで - /// - /// 与えられた密度から、回折パターンを計算. - /// 予め、PixelIndexやPixelIntnsityをSetDiffractedPixels()で設定しておく必要があり。 - /// - /// - /// - /// - public double[] GetSimulatedPattern(AreaDetector detector, int[] densityIndex, double[] densityValue) - { - var pixels = new double[detector.ImageLength]; - for (int i = 0; i < densityIndex.Length; i++) - if (Pixel[densityIndex[i]] != null) - foreach ((var Index, var Intensity) in Pixel[densityIndex[i]]) - pixels[Index] += Intensity * densityValue[i]; - return pixels; - } + return list.ToArray(); } - #region お蔵入り中のPowderクラス - /// - /// 多結晶体を取り扱う. + /// 与えられた密度から、回折パターンを計算. + /// 予め、PixelIndexやPixelIntnsityをSetDiffractedPixels()で設定しておく必要があり。 /// - [Serializable()] - public static class Powder + /// + /// + /// + public double[] GetSimulatedPattern(AreaDetector detector, double[] density = null) { - //public double GrainSize=1; - - //public Crystal BaseCrystal; - //public Matrix3D BaseRotation = new Matrix3D(); - //public List BaseRotationList = new List(); - - //public Crystallite[] Crysatallites; - - //Vector3DBase[] gVector; - //double[] intensity = new double[0]; - - //public double[][] CrystalliteRotations; - //public List[] indexeCandidates; + if (density == null) + density = Density; + + var pixels = new double[detector.ImageLength]; + for (int i = 0; i < TotalCrystalline; i++) + if (Pixel[i] != null) + foreach ((var Index, var Intensity) in Pixel[i]) + pixels[Index] += Intensity * density[i]; + return pixels; + } - // public PolyCrystal(Crystal baseCrystal,PolycrystallineProperty[] eachCrystals) - // { - //BaseCrystal = baseCrystal; - //Crysatallites = eachCrystals; - //GrainSize = grainSize; + /// + /// 与えられた密度から、回折パターンを計算. + /// 予め、PixelIndexやPixelIntnsityをSetDiffractedPixels()で設定しておく必要があり。 + /// + /// + /// + /// + public double[] GetSimulatedPattern(AreaDetector detector, int[] densityIndex, double[] densityValue) + { + var pixels = new double[detector.ImageLength]; + for (int i = 0; i < densityIndex.Length; i++) + if (Pixel[densityIndex[i]] != null) + foreach ((var Index, var Intensity) in Pixel[densityIndex[i]]) + pixels[Index] += Intensity * densityValue[i]; + return pixels; + } +} - // if (strain != null) - // baseCrystal.Strain = strain; - // if (stress != null) - // baseCrystal.Stress = stress; - // baseCrystal.HillCoefficient = hill; - // } +#region お蔵入り中のPowderクラス - //public void ResetBaseRotation() - //{ - // BaseRotationList.Clear(); - //} +/// +/// 多結晶体を取り扱う. +/// +[Serializable()] +public static class Powder +{ + //public double GrainSize=1; - // private PointD beforeCenter = new PointD(double.NaN, double.NaN); + //public Crystal BaseCrystal; + //public Matrix3D BaseRotation = new Matrix3D(); + //public List BaseRotationList = new List(); - public static double[] GetSimulatedPattern - (Crystal crystal, Crystallite crystallites, bool resetIndex, AreaDetector detector, YusaGonio gonio = null) - { - return Array.Empty(); - } + //public Crystallite[] Crysatallites; - /// - /// 多結晶体のディフラクションパターンを計算する - /// - /// 回転行列 - /// 既に計算済みの回折に寄与する逆格子ベクトルをリセットする。もともと計算していなかったらこの値に関わらず再計算する。 - /// イメージ中の各ピクセルが対応する逆空間ベクトルおよび面積をリセットする。もともと計算していなかったらこの値に関わらず再計算する。 - /// 逆格子点のベクトルや強度をリセットする。もともと計算していなかったらこの値に関わらず再計算する。 - /// 計算対象のCrystallite配列。省略すると、既定のCrystallitesを計算する。 - /// イメージ中の各ピクセルが対応する逆空間ベクトル。省略してもよい。 - /// イメージ中の各ピクセルが対応する逆空間面積。省略してもよい。 - /// YusaGonioを使用した場合の、設定値。省略してもよい。 - /// - /* public static double[] GetSimulatedPattern - (Crystal crystal, Crystallite crystallites, bool resetIndex, AreaDetector detector, YusaGonio gonio = null) - { - if (crystallites == null) - crystallites = crystal.Crystallites; + //Vector3DBase[] gVector; + //double[] intensity = new double[0]; - //BaseRotation = rotation; - //if (!BaseRotationList.Contains(rotation)) - //{ - // BaseRotationList.Add(rotation); - // resetIndex = true; - //} + //public double[][] CrystalliteRotations; + //public List[] indexeCandidates; - //まず各種定数の設定 - //if (renewRvector) - detector.SetReciprocalSpace(); + // public PolyCrystal(Crystal baseCrystal,PolycrystallineProperty[] eachCrystals) + // { + //BaseCrystal = baseCrystal; + //Crysatallites = eachCrystals; + //GrainSize = grainSize; - //if (resetIndex) - // crystallites.Index = new List[crystallites.TotalCrystalline]; + // if (strain != null) + // baseCrystal.Strain = strain; + // if (stress != null) + // baseCrystal.Stress = stress; + // baseCrystal.HillCoefficient = hill; + // } - double[] pixelsSum = getSimulatedPattern(crystal, crystallites, detector, gonio); + //public void ResetBaseRotation() + //{ + // BaseRotationList.Clear(); + //} - Parallel.For(0, pixelsSum.Length, i => - { - if (pixelsSum[i] != 0) - pixelsSum[i] *= detector.ReciprocalAreas [i] * 0.0001; - }); + // private PointD beforeCenter = new PointD(double.NaN, double.NaN); - return pixelsSum; - }*/ + public static double[] GetSimulatedPattern + (Crystal crystal, Crystallite crystallites, bool resetIndex, AreaDetector detector, YusaGonio gonio = null) + { + return Array.Empty(); + } - /* private double[] getSimulatedPattern(Crystallite[] crystals, int imageWidth, int imageHeight, double centerX, double centerY, double resolution, double convergence, double monochromaticity) + /// + /// 多結晶体のディフラクションパターンを計算する + /// + /// 回転行列 + /// 既に計算済みの回折に寄与する逆格子ベクトルをリセットする。もともと計算していなかったらこの値に関わらず再計算する。 + /// イメージ中の各ピクセルが対応する逆空間ベクトルおよび面積をリセットする。もともと計算していなかったらこの値に関わらず再計算する。 + /// 逆格子点のベクトルや強度をリセットする。もともと計算していなかったらこの値に関わらず再計算する。 + /// 計算対象のCrystallite配列。省略すると、既定のCrystallitesを計算する。 + /// イメージ中の各ピクセルが対応する逆空間ベクトル。省略してもよい。 + /// イメージ中の各ピクセルが対応する逆空間面積。省略してもよい。 + /// YusaGonioを使用した場合の、設定値。省略してもよい。 + /// + /* public static double[] GetSimulatedPattern + (Crystal crystal, Crystallite crystallites, bool resetIndex, AreaDetector detector, YusaGonio gonio = null) + { + if (crystallites == null) + crystallites = crystal.Crystallites; + + //BaseRotation = rotation; + //if (!BaseRotationList.Contains(rotation)) + //{ + // BaseRotationList.Add(rotation); + // resetIndex = true; + //} + + //まず各種定数の設定 + //if (renewRvector) + detector.SetReciprocalSpace(); + + //if (resetIndex) + // crystallites.Index = new List[crystallites.TotalCrystalline]; + + double[] pixelsSum = getSimulatedPattern(crystal, crystallites, detector, gonio); + + Parallel.For(0, pixelsSum.Length, i => { - return getSimulatedPattern(crystals, imageWidth, imageHeight, centerX, centerY, resolution, convergence, monochromaticity, Environment.ProcessorCount); - }*/ - /*static object lockThis=new object(); - private static double[] getSimulatedPattern(Crystal crystal, Crystallite crystallites, AreaDetector detector, YusaGonio gonio = null, int threadNumber = 0) + if (pixelsSum[i] != 0) + pixelsSum[i] *= detector.ReciprocalAreas [i] * 0.0001; + }); + + return pixelsSum; + }*/ + + /* private double[] getSimulatedPattern(Crystallite[] crystals, int imageWidth, int imageHeight, double centerX, double centerY, double resolution, double convergence, double monochromaticity) + { + return getSimulatedPattern(crystals, imageWidth, imageHeight, centerX, centerY, resolution, convergence, monochromaticity, Environment.ProcessorCount); + }*/ + /*static object lockThis=new object(); + private static double[] getSimulatedPattern(Crystal crystal, Crystallite crystallites, AreaDetector detector, YusaGonio gonio = null, int threadNumber = 0) + { + if (threadNumber == 0) + threadNumber = Environment.ProcessorCount; + + double[] pixels = new double[detector.ImageHeight * detector.ImageWidth]; + + Elasticity e = new Elasticity(crystal.ElasticStiffness, Elasticity.Mode.Stiffness); + bool strainFree = crystal.Stress.IsZero() && crystal.Strain.IsZero(); + bool rotationFree = crystallites.WholeRotation.IsIdentity(); + + double convergenceHK = Math.Sin(detector.Convergence / 2) / detector.WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸垂直な方向) + double convergenceHK2 = convergenceHK * convergenceHK; + //double convergenceZ = (1 - Math.Cos(convergence / 2)) / WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸平行な方向) //この成分は無視することにしよう + + double ewaldR = 1 / detector.WaveLength; + double ewaldR2 = ewaldR * ewaldR; + double monochromaticity2 = detector.Monochromaticity * detector.Monochromaticity; + double maxMonochroHK2 = 2 * detector.MaxReciproZ * ewaldR * monochromaticity2; //Z + double size = crystallites.GrainSizes[0]; + double reciprocalPointSize = 1 / size / 2; + double reciprocalPointSize2 = reciprocalPointSize * reciprocalPointSize; + double vol = size * size * size; + double maxExcitationError2 = reciprocalPointSize2 + maxMonochroHK2 + convergenceHK2; + double maxExcitationError = Math.Sqrt(maxExcitationError2); + + double hk2square = reciprocalPointSize2 + convergenceHK2; // (-y,x,0)方向の半値幅 + + int[] directions = new int[] { 0, -detector.ImageWidth - 1, -detector.ImageWidth, -detector.ImageWidth + 1, -1, 1, detector.ImageWidth - 1, detector.ImageWidth, detector.ImageWidth + 1 }; + ParallelOptions p = new ParallelOptions(); + p.MaxDegreeOfParallelism = threadNumber; + + //YusaGonioMatrixを初期化 + int repetation = 1; + if (gonio != null && gonio.Valid) + repetation = 30 * 30; + Matrix3D[] yusaGonioMatrix = new Matrix3D[repetation]; + for (int l = 0; l < repetation; l++) { - if (threadNumber == 0) - threadNumber = Environment.ProcessorCount; - - double[] pixels = new double[detector.ImageHeight * detector.ImageWidth]; - - Elasticity e = new Elasticity(crystal.ElasticStiffness, Elasticity.Mode.Stiffness); - bool strainFree = crystal.Stress.IsZero() && crystal.Strain.IsZero(); - bool rotationFree = crystallites.WholeRotation.IsIdentity(); + yusaGonioMatrix[l] = new Matrix3D(); + if (repetation != 1) + { + if (gonio.Rx) + yusaGonioMatrix[l] = Matrix3D.Rot(new Vector3D(0, 0, 1), 2 * Math.PI * (double)l / repetation) * yusaGonioMatrix[l]; + //z,yの格子間隔を計算 + int zNum = (int)Math.Sqrt(repetation); + int yNum = (int)Math.Sqrt(repetation); + double zStart = -gonio.Rz_OscillationRange / 180 * Math.PI; + double yStart = -gonio.Ry_OscillationRange / 180 * Math.PI; + double zDiv = (gonio.Rz_OscillationRange * 2) / zNum / 180 * Math.PI; + double yDiv = (gonio.Ry_OscillationRange * 2) / yNum / 180 * Math.PI; + yusaGonioMatrix[l] = Matrix3D.Rot(new Vector3D(0, 1, 0), zStart + (l % zNum) * zDiv) * yusaGonioMatrix[l]; + yusaGonioMatrix[l] = Matrix3D.Rot(new Vector3D(1, 0, 0), yStart + (l / yNum) * yDiv) * yusaGonioMatrix[l]; + } + } + //YusaGonioMatrixを初期化ここまで - double convergenceHK = Math.Sin(detector.Convergence / 2) / detector.WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸垂直な方向) - double convergenceHK2 = convergenceHK * convergenceHK; - //double convergenceZ = (1 - Math.Cos(convergence / 2)) / WaveLength;//逆空間での、収束による逆格子点のにじみ(X線軸平行な方向) //この成分は無視することにしよう + for (int l = 0; l < repetation; l++) + { + if (repetation != 1) + for (int m = 0; m < crystallites.TotalCrystalline; m++) + crystallites.Index[m] = null; - double ewaldR = 1 / detector.WaveLength; - double ewaldR2 = ewaldR * ewaldR; - double monochromaticity2 = detector.Monochromaticity * detector.Monochromaticity; - double maxMonochroHK2 = 2 * detector.MaxReciproZ * ewaldR * monochromaticity2; //Z - double size = crystallites.GrainSizes[0]; - double reciprocalPointSize = 1 / size / 2; - double reciprocalPointSize2 = reciprocalPointSize * reciprocalPointSize; - double vol = size * size * size; - double maxExcitationError2 = reciprocalPointSize2 + maxMonochroHK2 + convergenceHK2; - double maxExcitationError = Math.Sqrt(maxExcitationError2); - - double hk2square = reciprocalPointSize2 + convergenceHK2; // (-y,x,0)方向の半値幅 - - int[] directions = new int[] { 0, -detector.ImageWidth - 1, -detector.ImageWidth, -detector.ImageWidth + 1, -1, 1, detector.ImageWidth - 1, detector.ImageWidth, detector.ImageWidth + 1 }; - ParallelOptions p = new ParallelOptions(); - p.MaxDegreeOfParallelism = threadNumber; - - //YusaGonioMatrixを初期化 - int repetation = 1; - if (gonio != null && gonio.Valid) - repetation = 30 * 30; - Matrix3D[] yusaGonioMatrix = new Matrix3D[repetation]; - for (int l = 0; l < repetation; l++) + //エワルド球に近い(回折条件に引っ掛かる)逆格子ベクトルを探索 + Parallel.For(0, crystallites.TotalCrystalline, p, i => { - yusaGonioMatrix[l] = new Matrix3D(); - if (repetation != 1) + if (crystallites.Index[i] == null)//crystal[i].index が設定されていないとき { - if (gonio.Rx) - yusaGonioMatrix[l] = Matrix3D.Rot(new Vector3D(0, 0, 1), 2 * Math.PI * (double)l / repetation) * yusaGonioMatrix[l]; - //z,yの格子間隔を計算 - int zNum = (int)Math.Sqrt(repetation); - int yNum = (int)Math.Sqrt(repetation); - double zStart = -gonio.Rz_OscillationRange / 180 * Math.PI; - double yStart = -gonio.Ry_OscillationRange / 180 * Math.PI; - double zDiv = (gonio.Rz_OscillationRange * 2) / zNum / 180 * Math.PI; - double yDiv = (gonio.Ry_OscillationRange * 2) / yNum / 180 * Math.PI; - yusaGonioMatrix[l] = Matrix3D.Rot(new Vector3D(0, 1, 0), zStart + (l % zNum) * zDiv) * yusaGonioMatrix[l]; - yusaGonioMatrix[l] = Matrix3D.Rot(new Vector3D(1, 0, 0), yStart + (l / yNum) * yDiv) * yusaGonioMatrix[l]; - } - } - //YusaGonioMatrixを初期化ここまで + Matrix3D rotation = crystallites.CrystallineRotations[i]; + if (repetation != 1) + rotation = yusaGonioMatrix[l] * rotation; - for (int l = 0; l < repetation; l++) - { - if (repetation != 1) - for (int m = 0; m < crystallites.TotalCrystalline; m++) - crystallites.Index[m] = null; + if (!strainFree) + rotation = (e.GetStrainByHill(crystal.Symmetry, crystallites.CrystallineRotations[i], crystal.Stress, crystal.Strain, crystal.HillCoefficient) + new Matrix3D()).Inverse() * rotation; + if (crystallites.Index[i] == null) + crystallites.Index[i] = new List(); - //エワルド球に近い(回折条件に引っ掛かる)逆格子ベクトルを探索 - Parallel.For(0, crystallites.TotalCrystalline, p, i => - { - if (crystallites.Index[i] == null)//crystal[i].index が設定されていないとき + // for (int j = 0; j < crystallites.WholeRotations.Count; j++) { - Matrix3D rotation = crystallites.CrystallineRotations[i]; - if (repetation != 1) - rotation = yusaGonioMatrix[l] * rotation; - - if (!strainFree) - rotation = (e.GetStrainByHill(crystal.Symmetry, crystallites.CrystallineRotations[i], crystal.Stress, crystal.Strain, crystal.HillCoefficient) + new Matrix3D()).Inverse() * rotation; - if (crystallites.Index[i] == null) - crystallites.Index[i] = new List(); + if (!rotationFree) + rotation = crystallites.WholeRotation * rotation; - // for (int j = 0; j < crystallites.WholeRotations.Count; j++) + double x = 0, y = 0, z = 0; + for (int n = 0; n < crystallites.G_Vector.Length; n++) { - if (!rotationFree) - rotation = crystallites.WholeRotation * rotation; - - double x = 0, y = 0, z = 0; - for (int n = 0; n < crystallites.G_Vector.Length; n++) + Vector3DBase g = crystallites.G_Vector[n]; + z = n % 2 == 0 ? rotation.E31 * g.X + rotation.E32 * g.Y + rotation.E33 * g.Z : -z; + if (z > -maxExcitationError * 2 && detector.MaxReciproZ + maxExcitationError * 2 > z) { - Vector3DBase g = crystallites.G_Vector[n]; - z = n % 2 == 0 ? rotation.E31 * g.X + rotation.E32 * g.Y + rotation.E33 * g.Z : -z; - if (z > -maxExcitationError * 2 && detector.MaxReciproZ + maxExcitationError * 2 > z) + double rz = ewaldR - z; + x = rotation.E11 * g.X + rotation.E12 * g.Y + rotation.E13 * g.Z; + y = rotation.E21 * g.X + rotation.E22 * g.Y + rotation.E23 * g.Z; + double ptX = detector.CameraLength / detector.Resolution / rz * x + detector.Center.X; + double ptY = -detector.CameraLength / detector.Resolution / rz * y + detector.Center.Y; + if (ptX < detector.ImageWidth - 1 && ptX > 0 && ptY < detector.ImageHeight - 1 && ptY > 0) { - double rz = ewaldR - z; - x = rotation.E11 * g.X + rotation.E12 * g.Y + rotation.E13 * g.Z; - y = rotation.E21 * g.X + rotation.E22 * g.Y + rotation.E23 * g.Z; - double ptX = detector.CameraLength / detector.Resolution / rz * x + detector.Center.X; - double ptY = -detector.CameraLength / detector.Resolution / rz * y + detector.Center.Y; - if (ptX < detector.ImageWidth - 1 && ptX > 0 && ptY < detector.ImageHeight - 1 && ptY > 0) - { - //エワルド球面が、試料近傍で平面近似できるとして計算する 楕円(x-X)^2/hk1^2 + (z-Z)^2/hk3^2 == 1 と 直線 y = X/(R-Z) x + R(1-sqrt(X^2/(R-Z)^2+1)) の連立方程式を解く - double xyLength2 = x * x + y * y; - double hk1square = hk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 - double hk3square = reciprocalPointSize2 + monochromaticity2 * z * z;// (0,0,z)方向の半値幅 - double hk3per1 = hk3square / hk1square; - double sqrt = Math.Sqrt(1 + xyLength2 / rz / rz); - double a = hk3per1 + xyLength2 / rz / rz; - double b2 = (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * xyLength2; - double c = -hk3square * 4 + 2 * ewaldR * (ewaldR - rz * sqrt - z) + hk3per1 * xyLength2 + ewaldR2 * xyLength2 / rz / rz + z * z;//最初の項hk3へ書ける数値が許容半値幅の二乗 - if (b2 - a * c >= 0 && !crystallites.Index[i].Contains(n)) - crystallites.Index[i].Add(n); - } + //エワルド球面が、試料近傍で平面近似できるとして計算する 楕円(x-X)^2/hk1^2 + (z-Z)^2/hk3^2 == 1 と 直線 y = X/(R-Z) x + R(1-sqrt(X^2/(R-Z)^2+1)) の連立方程式を解く + double xyLength2 = x * x + y * y; + double hk1square = hk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 + double hk3square = reciprocalPointSize2 + monochromaticity2 * z * z;// (0,0,z)方向の半値幅 + double hk3per1 = hk3square / hk1square; + double sqrt = Math.Sqrt(1 + xyLength2 / rz / rz); + double a = hk3per1 + xyLength2 / rz / rz; + double b2 = (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * xyLength2; + double c = -hk3square * 4 + 2 * ewaldR * (ewaldR - rz * sqrt - z) + hk3per1 * xyLength2 + ewaldR2 * xyLength2 / rz / rz + z * z;//最初の項hk3へ書ける数値が許容半値幅の二乗 + if (b2 - a * c >= 0 && !crystallites.Index[i].Contains(n)) + crystallites.Index[i].Add(n); } } } } - });//エワルド球に近い逆格子ベクトルを探索 ここまで + } + });//エワルド球に近い逆格子ベクトルを探索 ここまで - //探索した逆格子ベクトルの回折位置・強度計算 - Parallel.For(0, crystallites.TotalCrystalline, p, i => + //探索した逆格子ベクトルの回折位置・強度計算 + Parallel.For(0, crystallites.TotalCrystalline, p, i => + { + if (crystallites.Index[i].Count > 0) { - if (crystallites.Index[i].Count > 0) - { - Matrix3D rotation = crystallites.CrystallineRotations[i]; + Matrix3D rotation = crystallites.CrystallineRotations[i]; - if (repetation != 1) - rotation = yusaGonioMatrix[l] * rotation; + if (repetation != 1) + rotation = yusaGonioMatrix[l] * rotation; - if (!strainFree) - rotation = (e.GetStrainByHill(crystal.Symmetry, crystallites.CrystallineRotations[i],crystal.Stress, crystal.Strain, crystal.HillCoefficient) + new Matrix3D()).Inverse() * rotation; + if (!strainFree) + rotation = (e.GetStrainByHill(crystal.Symmetry, crystallites.CrystallineRotations[i],crystal.Stress, crystal.Strain, crystal.HillCoefficient) + new Matrix3D()).Inverse() * rotation; - //if (!rotationFree) - // rotation = BaseRotation * rotation; + //if (!rotationFree) + // rotation = BaseRotation * rotation; - double x = 0, y = 0, z = 0; + double x = 0, y = 0, z = 0; - foreach (int n in crystallites.Index[i]) - { - Vector3DBase g = crystallites.G_Vector[n]; - x = rotation.E11 * g.X + rotation.E12 * g.Y + rotation.E13 * g.Z; - y = rotation.E21 * g.X + rotation.E22 * g.Y + rotation.E23 * g.Z; - z = rotation.E31 * g.X + rotation.E32 * g.Y + rotation.E33 *g.Z; - - double xyLength2 = x * x + y * y; - double xyLength = Math.Sqrt(xyLength2); - double hk1square = hk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 - double hk3square = reciprocalPointSize2 + monochromaticity2 * z * z;// (0,0,z)方向の半値幅 - double intensityTemp = 1 / Math.Sqrt(hk1square * 1000 * hk2square * 1000 * hk3square * 1000) * vol / 1000 * crystallites.G_Intensity[n];// *crystals[i].Density; - if (repetation != 1) - intensityTemp = intensityTemp / repetation; - - List comp = new List();//計算済みピクセル - //初期位置の計算 - double rz = ewaldR - z; - double a = hk3square / hk1square + xyLength2 / rz / rz; - double b = (hk3square / hk1square + (ewaldR * Math.Sqrt(1 + xyLength2 / rz / rz) - ewaldR + z) / rz) * xyLength; - double XY = Math.Abs(b / a); - double d = detector.CameraLength / detector.Resolution / Math.Sqrt(ewaldR2 - XY * XY) / xyLength * XY; - List rim = new List(new int[] { (int)(-d * y + detector.Center.Y + 0.5) * detector.ImageWidth + (int)(d * x + detector.Center.X + 0.5) });//初期外縁ピクセル - - for (int j = 0; j < rim.Count; j++)//rim.RemoveAt(0))//現在のピクセル位置から、周辺強度を計算していって、半値幅の2倍以上になったら終了 - for (int k = j == 0 ? 0 : 1; k < directions.Length; k++) + foreach (int n in crystallites.Index[i]) + { + Vector3DBase g = crystallites.G_Vector[n]; + x = rotation.E11 * g.X + rotation.E12 * g.Y + rotation.E13 * g.Z; + y = rotation.E21 * g.X + rotation.E22 * g.Y + rotation.E23 * g.Z; + z = rotation.E31 * g.X + rotation.E32 * g.Y + rotation.E33 *g.Z; + + double xyLength2 = x * x + y * y; + double xyLength = Math.Sqrt(xyLength2); + double hk1square = hk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 + double hk3square = reciprocalPointSize2 + monochromaticity2 * z * z;// (0,0,z)方向の半値幅 + double intensityTemp = 1 / Math.Sqrt(hk1square * 1000 * hk2square * 1000 * hk3square * 1000) * vol / 1000 * crystallites.G_Intensity[n];// *crystals[i].Density; + if (repetation != 1) + intensityTemp = intensityTemp / repetation; + + List comp = new List();//計算済みピクセル + //初期位置の計算 + double rz = ewaldR - z; + double a = hk3square / hk1square + xyLength2 / rz / rz; + double b = (hk3square / hk1square + (ewaldR * Math.Sqrt(1 + xyLength2 / rz / rz) - ewaldR + z) / rz) * xyLength; + double XY = Math.Abs(b / a); + double d = detector.CameraLength / detector.Resolution / Math.Sqrt(ewaldR2 - XY * XY) / xyLength * XY; + List rim = new List(new int[] { (int)(-d * y + detector.Center.Y + 0.5) * detector.ImageWidth + (int)(d * x + detector.Center.X + 0.5) });//初期外縁ピクセル + + for (int j = 0; j < rim.Count; j++)//rim.RemoveAt(0))//現在のピクセル位置から、周辺強度を計算していって、半値幅の2倍以上になったら終了 + for (int k = j == 0 ? 0 : 1; k < directions.Length; k++) + { + int pos = rim[j] + directions[k]; + if ((j == 0 || !comp.Contains(pos)) && pos > -1 && pos < pixels.Length) { - int pos = rim[j] + directions[k]; - if ((j == 0 || !comp.Contains(pos)) && pos > -1 && pos < pixels.Length) + comp.Add(pos); + double temp1 = x * detector.ReciprocalVectors[pos].X + y * detector.ReciprocalVectors[pos].Y - xyLength2; + double temp2 = x * detector.ReciprocalVectors[pos].Y - y * detector.ReciprocalVectors[pos].X; + double dev2 = temp1 * temp1 / xyLength2 / hk1square + temp2 * temp2 / xyLength2 / hk2square + (z - detector.ReciprocalVectors[pos].Z) * (z - detector.ReciprocalVectors[pos].Z) / hk3square; + if (dev2 < 5.0) { - comp.Add(pos); - double temp1 = x * detector.ReciprocalVectors[pos].X + y * detector.ReciprocalVectors[pos].Y - xyLength2; - double temp2 = x * detector.ReciprocalVectors[pos].Y - y * detector.ReciprocalVectors[pos].X; - double dev2 = temp1 * temp1 / xyLength2 / hk1square + temp2 * temp2 / xyLength2 / hk2square + (z - detector.ReciprocalVectors[pos].Z) * (z - detector.ReciprocalVectors[pos].Z) / hk3square; - if (dev2 < 5.0) + double temp = Math.Exp(-dev2) * intensityTemp;//double temp = intensityTemp / (1.0 + dev2); + lock (lockThis) { - double temp = Math.Exp(-dev2) * intensityTemp;//double temp = intensityTemp / (1.0 + dev2); - lock (lockThis) - { - pixels[pos] += temp; - if (k != 0) - rim.Add(pos); - } + pixels[pos] += temp; + if (k != 0) + rim.Add(pos); } } } - } + } } - });//探索した逆格子ベクトルの回折位置・強度計算 ここまで - } + } + });//探索した逆格子ベクトルの回折位置・強度計算 ここまで + } - if (repetation != 1)//YusaGonioの時だけ、もう一度スキャン - for (int l = 0; l < repetation; l++) + if (repetation != 1)//YusaGonioの時だけ、もう一度スキャン + for (int l = 0; l < repetation; l++) + { + //エワルド球に近い(回折条件に引っ掛かる)逆格子ベクトルを探索 + Parallel.For(0, crystallites.TotalCrystalline, p, i => { - //エワルド球に近い(回折条件に引っ掛かる)逆格子ベクトルを探索 - Parallel.For(0, crystallites.TotalCrystalline, p, i => - { - Matrix3D rotation = crystallites.CrystallineRotations[i]; - rotation = yusaGonioMatrix[l] * rotation; + Matrix3D rotation = crystallites.CrystallineRotations[i]; + rotation = yusaGonioMatrix[l] * rotation; - if (!strainFree) - rotation = (e.GetStrainByHill(crystal.Symmetry, crystallites.CrystallineRotations[i], crystal.Stress, crystal.Strain, crystal.HillCoefficient) + new Matrix3D()).Inverse() * rotation; - if (crystallites.Index[i] == null) - crystallites.Index[i] = new List(); + if (!strainFree) + rotation = (e.GetStrainByHill(crystal.Symmetry, crystallites.CrystallineRotations[i], crystal.Stress, crystal.Strain, crystal.HillCoefficient) + new Matrix3D()).Inverse() * rotation; + if (crystallites.Index[i] == null) + crystallites.Index[i] = new List(); - //for (int j = 0; j < crystallites.WholeRotations.Count; j++) - { - if (!rotationFree) - rotation = crystallites.WholeRotation * rotation; + //for (int j = 0; j < crystallites.WholeRotations.Count; j++) + { + if (!rotationFree) + rotation = crystallites.WholeRotation * rotation; - double x = 0, y = 0, z = 0; - for (int n = 0; n < crystallites.G_VectorNumber; n++) + double x = 0, y = 0, z = 0; + for (int n = 0; n < crystallites.G_VectorNumber; n++) + { + Vector3DBase g = crystallites.G_Vector[n]; + z = n % 2 == 0 ? rotation.E31 * g.X + rotation.E32 * g.Y + rotation.E33 * g.Z : -z; + if (z > -maxExcitationError * 2 && detector.MaxReciproZ + maxExcitationError * 2 > z) { - Vector3DBase g = crystallites.G_Vector[n]; - z = n % 2 == 0 ? rotation.E31 * g.X + rotation.E32 * g.Y + rotation.E33 * g.Z : -z; - if (z > -maxExcitationError * 2 && detector.MaxReciproZ + maxExcitationError * 2 > z) + double rz = ewaldR - z; + x = rotation.E11 * g.X + rotation.E12 * g.Y + rotation.E13 * g.Z; + y = rotation.E21 * g.X + rotation.E22 * g.Y + rotation.E23 * g.Z; + double ptX = detector.CameraLength / detector.Resolution / rz * x + detector.Center.X; + double ptY = -detector.CameraLength / detector.Resolution / rz * y + detector.Center.Y; + if (ptX < detector.ImageWidth - 1 && ptX > 0 && ptY < detector.ImageHeight - 1 && ptY > 0) { - double rz = ewaldR - z; - x = rotation.E11 * g.X + rotation.E12 * g.Y + rotation.E13 * g.Z; - y = rotation.E21 * g.X + rotation.E22 * g.Y + rotation.E23 * g.Z; - double ptX = detector.CameraLength / detector.Resolution / rz * x + detector.Center.X; - double ptY = -detector.CameraLength / detector.Resolution / rz * y + detector.Center.Y; - if (ptX < detector.ImageWidth - 1 && ptX > 0 && ptY < detector.ImageHeight - 1 && ptY > 0) - { - //エワルド球面が、試料近傍で平面近似できるとして計算する 楕円(x-X)^2/hk1^2 + (z-Z)^2/hk3^2 == 1 と 直線 y = X/(R-Z) x + R(1-sqrt(X^2/(R-Z)^2+1)) の連立方程式を解く - double xyLength2 = x * x + y * y; - double hk1square = hk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 - double hk3square = reciprocalPointSize2 + monochromaticity2 * z * z;// (0,0,z)方向の半値幅 - double hk3per1 = hk3square / hk1square; - double sqrt = Math.Sqrt(1 + xyLength2 / rz / rz); - double a = hk3per1 + xyLength2 / rz / rz; - double b2 = (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * xyLength2; - double c = -hk3square * 4 + 2 * ewaldR * (ewaldR - rz * sqrt - z) + hk3per1 * xyLength2 + ewaldR2 * xyLength2 / rz / rz + z * z;//最初の項hk3へ書ける数値が許容半値幅の二乗 - if (b2 - a * c >= 0 && !crystallites.Index[i].Contains(n)) - crystallites.Index[i].Add(n); - } + //エワルド球面が、試料近傍で平面近似できるとして計算する 楕円(x-X)^2/hk1^2 + (z-Z)^2/hk3^2 == 1 と 直線 y = X/(R-Z) x + R(1-sqrt(X^2/(R-Z)^2+1)) の連立方程式を解く + double xyLength2 = x * x + y * y; + double hk1square = hk2square + monochromaticity2 * xyLength2;//(x,y,0)方向の半値幅 + double hk3square = reciprocalPointSize2 + monochromaticity2 * z * z;// (0,0,z)方向の半値幅 + double hk3per1 = hk3square / hk1square; + double sqrt = Math.Sqrt(1 + xyLength2 / rz / rz); + double a = hk3per1 + xyLength2 / rz / rz; + double b2 = (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * (hk3per1 + (ewaldR * sqrt - ewaldR + z) / rz) * xyLength2; + double c = -hk3square * 4 + 2 * ewaldR * (ewaldR - rz * sqrt - z) + hk3per1 * xyLength2 + ewaldR2 * xyLength2 / rz / rz + z * z;//最初の項hk3へ書ける数値が許容半値幅の二乗 + if (b2 - a * c >= 0 && !crystallites.Index[i].Contains(n)) + crystallites.Index[i].Add(n); } } } - });//エワルド球に近い逆格子ベクトルを探索 ここまで - } - - return pixels; - } + } + });//エワルド球に近い逆格子ベクトルを探索 ここまで + } - */ + return pixels; } - #endregion お蔵入り中のPowderクラス -} \ No newline at end of file + */ +} + +#endregion お蔵入り中のPowderクラス diff --git a/Crystallography/Crystallography.csproj b/Crystallography/Crystallography.csproj index c3802fb..ace82ac 100644 --- a/Crystallography/Crystallography.csproj +++ b/Crystallography/Crystallography.csproj @@ -2,11 +2,12 @@ Library - net8.0-windows10.0.22621.0 + net8.0-windows10.0.26100.0 true - 2024.7.4.1116 - 2024.7.4.1116 + 2024.10.4.0923 + 2024.10.4.0923 7.0 + AnyCPU;x64 @@ -14,10 +15,19 @@ False + + true + False + + true + + true + + @@ -25,10 +35,10 @@ - + - + diff --git a/Crystallography/Detector/Ring.cs b/Crystallography/Detector/Ring.cs index 26a1ec7..0e3d3fb 100644 --- a/Crystallography/Detector/Ring.cs +++ b/Crystallography/Detector/Ring.cs @@ -1234,20 +1234,20 @@ public static double[] GetCorrectedImageArray(IntegralProperty iP, double resolu if (minX < size.Width && maxX >= 0 && minY < size.Height && maxY >= 0) { - double totalArea = Geometriy.GetPolygonalArea(pixelVertex); + double totalArea = Geometry.GetPolygonalArea(pixelVertex); double intensity = Intensity[j * IP.SrcWidth + i]; for (int pixX = Math.Max(0, minX); pixX <= Math.Min(size.Width - 1, maxX); pixX++) for (int pixY = Math.Max(0, minY); pixY <= Math.Min(size.Height - 1, maxY); pixY++) { PointD[] tempPixelVertex; - tempPixelVertex = Geometriy.GetPolygonDividedByLine(pixelVertex, 1, 0, (pixX - center.X - 0.5) * resolution); - tempPixelVertex = Geometriy.GetPolygonDividedByLine(tempPixelVertex, -1, 0, -(pixX - center.X + 0.5) * resolution); - tempPixelVertex = Geometriy.GetPolygonDividedByLine(tempPixelVertex, 0, 1, (pixY - center.Y - 0.5) * resolution); - tempPixelVertex = Geometriy.GetPolygonDividedByLine(tempPixelVertex, 0, -1, -(pixY - center.Y + 0.5) * resolution); + tempPixelVertex = Geometry.GetPolygonDividedByLine(pixelVertex, 1, 0, (pixX - center.X - 0.5) * resolution); + tempPixelVertex = Geometry.GetPolygonDividedByLine(tempPixelVertex, -1, 0, -(pixX - center.X + 0.5) * resolution); + tempPixelVertex = Geometry.GetPolygonDividedByLine(tempPixelVertex, 0, 1, (pixY - center.Y - 0.5) * resolution); + tempPixelVertex = Geometry.GetPolygonDividedByLine(tempPixelVertex, 0, -1, -(pixY - center.Y + 0.5) * resolution); //面積比を求めて強度を割り振り - double currentArea = Geometriy.GetPolygonalArea(tempPixelVertex); + double currentArea = Geometry.GetPolygonalArea(tempPixelVertex); double ratio = currentArea / totalArea; pixels[pixY * size.Width + pixX] += ratio * intensity; } @@ -1662,7 +1662,7 @@ private static Profile GetRadialProfile(IntegralProperty iP) } } (pixelVertex[3], pixelVertex[2]) = (pixelVertex[2], pixelVertex[3]); - double totalArea = Geometriy.GetPolygonalArea(pixelVertex); + double totalArea = Geometry.GetPolygonalArea(pixelVertex); //求めた4隅の点から、ステップの指数の上限、下限を設定 List angles = []; @@ -1685,17 +1685,17 @@ private static Profile GetRadialProfile(IntegralProperty iP) //まずindexで定義される放射状の2本の直線の定義 double a1 = -Math.Sin((index - 0.5) * step), b1 = Math.Cos((index - 0.5) * step); double a2 = Math.Sin((index + 0.5) * step), b2 = -Math.Cos((index + 0.5) * step); - tempPixelVertex = Geometriy.GetPolygonDividedByLine(pixelVertex, a1, b1, 0); - tempPixelVertex = Geometriy.GetPolygonDividedByLine(tempPixelVertex, a2, b2, 0); + tempPixelVertex = Geometry.GetPolygonDividedByLine(pixelVertex, a1, b1, 0); + tempPixelVertex = Geometry.GetPolygonDividedByLine(tempPixelVertex, a2, b2, 0); //さらに角度範囲の上限、下限を表す同心円状の2直線 a1 = Math.Cos(index * step); b1 = Math.Sin(index * step); - tempPixelVertex = Geometriy.GetPolygonDividedByLine(tempPixelVertex, a1, b1, minR); - tempPixelVertex = Geometriy.GetPolygonDividedByLine(tempPixelVertex, -a1, -b1, -maxR); + tempPixelVertex = Geometry.GetPolygonDividedByLine(tempPixelVertex, a1, b1, minR); + tempPixelVertex = Geometry.GetPolygonDividedByLine(tempPixelVertex, -a1, -b1, -maxR); //面積比を求めて強度を割り振り - double currentArea = Geometriy.GetPolygonalArea(tempPixelVertex); + double currentArea = Geometry.GetPolygonalArea(tempPixelVertex); double ratio = currentArea / totalArea; tempProfileIntensity[index] += ratio * intensity; } @@ -2202,7 +2202,7 @@ private static void GetProfileGandlfi(int xMin, int xMax, int yMin, int yMax, re double vqZY2 = vq.X * v.X + vq.Y * v.Y; double vqZ2 = vq.Z * vq.Z; - double totalArea = Geometriy.GetPolygonalArea(p), residualArea = totalArea; + double totalArea = Geometry.GetPolygonalArea(p), residualArea = totalArea; for (int i = minIndex; i <= maxIndex; i++) { if (divisions[i] < minTwoTheta) @@ -2220,8 +2220,8 @@ private static void GetProfileGandlfi(int xMin, int xMax, int yMin, int yMax, re var d = Math.Abs((d1 + d2) / d3) < Math.Abs((d1 - d2) / d3) ? (d1 + d2) / d3 : (d1 - d2) / d3; - p = Geometriy.GetPolygonDividedByLine(p, 0, 1, d); - var area = Geometriy.GetPolygonalArea(p); + p = Geometry.GetPolygonDividedByLine(p, 0, 1, d); + var area = Geometry.GetPolygonalArea(p); if (i > 0) { profile[i - 1] += intensity * (residualArea - area) / totalArea; diff --git a/Crystallography/ExtensionMethods.cs b/Crystallography/ExtensionMethods.cs index 675b5dc..9e8ace4 100644 --- a/Crystallography/ExtensionMethods.cs +++ b/Crystallography/ExtensionMethods.cs @@ -1,13 +1,20 @@ -using MathNet.Numerics.LinearAlgebra; +#region using + +using MathNet.Numerics.LinearAlgebra; using MathNet.Numerics.LinearAlgebra.Double; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Numerics; +using System.Windows.Forms; +using System.Windows.Forms.VisualStyles; +using Windows.UI.ViewManagement.Core; using DMat = MathNet.Numerics.LinearAlgebra.Complex.DenseMatrix; using MC = Crystallography.MathematicalConstants; +#endregion + namespace Crystallography; #region MathNet の拡張 @@ -249,6 +256,9 @@ public static class HKL public static (int H, int K, int L) Plus(ref this (int H, int K, int L) x, (int H, int K, int L) y) => (x.H + y.H, x.K + y.K, x.L + y.L); public static (int H, int K, int L) Minus(ref this (int H, int K, int L) x, (int H, int K, int L) y) => (x.H - y.H, x.K - y.K, x.L - y.L); public static int Multiply(ref this (int H, int K, int L) x, (int H, int K, int L) y) => x.H * y.H + x.K * y.K + x.L * y.L; + + public static (int H, int K, int L) Cross(ref this (int H, int K, int L) x, (int H, int K, int L) y) + => (x.K * y.L - x.L * y.K, x.L * y.H - x.H * y.L, x.H * y.K - x.K * y.H); } #endregion @@ -328,6 +338,12 @@ public static class DoubleEx /// public static class GraphicsAlpha { + #region 座標変換 + public static void TranslateTransform(this Graphics g, double x, double y) => g.TranslateTransform((float)x, (float)y); + + public static void RotateTransform(this Graphics g, double angle_radians) => g.RotateTransform((float)(angle_radians / Math.PI * 180)); + #endregion + public static void DrawArc(this Graphics g, Pen pen, double x, double y, double width, double height, double startAngle, double sweepAngle) => g.DrawArc(pen, (float)x, (float)y, (float)width, (float)height, (float)startAngle, (float)sweepAngle); @@ -373,6 +389,205 @@ public static void DrawCircle(this Graphics graphics, in Color c, in PointD pt, if (Math.Abs(pt.X) < 1E6 && Math.Abs(pt.Y) < 1E6) graphics.DrawEllipse(new Pen(c, 0.0001f), (float)(pt.X - radius), (float)(pt.Y - radius), (float)(2 * radius), (float)(2 * radius)); } + + /// + /// 拡張メソッド + /// + /// + /// + /// + /// + /// + /// + /// + public static void DrawString(this Graphics graphics, string s, Font font, Color color, double x, double y, bool resetTransform = false) + { + var transform = graphics.Transform; + if (resetTransform) + graphics.Transform = new System.Drawing.Drawing2D.Matrix(1, 0, 0, 1, 1, 1); + + graphics.DrawString(s, font, new SolidBrush(color), (float)x, (float)y); + + if (resetTransform) + graphics.Transform = transform; + } + + public static void DrawString(this Graphics graphics, string s, Font font, Color color, PointD pt, bool resetTransform = false) + => DrawString(graphics, s, font, color, pt.X, pt.Y, resetTransform); + + /// + /// + /// + /// + /// 描画する文字列 + /// 描画に使用するフォント + /// 描画色 + /// 描画位置 + /// これ以上大きいことはないというサイズ。できるだけ小さくすること。 + /// 水平方向のアラインメント + /// 垂直方向のアラインメント + + public static void DrawStringWithAlignment + (this Graphics graphics, string text, Font font, Color color, PointD pt, Size maximumSize, HorizontalAlignment horizontal, VerticalAlignment vertical) + { + + var rect = MeasureStringPrecisely(graphics, text, font, maximumSize, new StringFormat()); + + float x= (float)pt.X, y = (float)pt.Y ; + if (horizontal == HorizontalAlignment.Right) + x -= rect.Width; + else if(horizontal == HorizontalAlignment.Center) + x -= rect.Width/2f; + if(vertical == VerticalAlignment.Center) + y -= rect.Height/2f; + else if (vertical == VerticalAlignment.Bottom) + y -= rect.Height; + + graphics.DrawString(text, font, new SolidBrush(color), x, y); + } + + /// + /// Graphics.DrawStringで文字列を描画した時の大きさと位置を正確に計測する + /// + /// 文字列を描画するGraphics + /// 描画する文字列 + /// 描画に使用するフォント + /// これ以上大きいことはないというサイズ。 + /// できるだけ小さくすること。 + /// 描画に使用するStringFormat + /// 文字列が描画される範囲。 + /// 見つからなかった時は、Rectangle.Empty。 + public static Rectangle MeasureStringPrecisely(Graphics g, + string text, Font font, Size proposedSize, StringFormat stringFormat) + { + //解像度を引き継いで、Bitmapを作成する + Bitmap bmp = new Bitmap(proposedSize.Width, proposedSize.Height, g); + //BitmapのGraphicsを作成する + Graphics bmpGraphics = Graphics.FromImage(bmp); + //Graphicsのプロパティを引き継ぐ + bmpGraphics.TextRenderingHint = g.TextRenderingHint; + bmpGraphics.TextContrast = g.TextContrast; + bmpGraphics.PixelOffsetMode = g.PixelOffsetMode; + bmpGraphics.Transform = g.Transform; + //文字列の描かれていない部分の色を取得する + Color backColor = bmp.GetPixel(0, 0); + //実際にBitmapに文字列を描画する + bmpGraphics.DrawString(text, font, Brushes.Black, + new RectangleF(0f, 0f, proposedSize.Width, proposedSize.Height), + stringFormat); + bmpGraphics.Dispose(); + //文字列が描画されている範囲を計測する + Rectangle resultRect = MeasureForegroundArea(bmp, backColor); + bmp.Dispose(); + + return resultRect; + } + + /// + /// 指定されたBitmapで、backColor以外の色が使われている範囲を計測する + /// + private static Rectangle MeasureForegroundArea(Bitmap bmp, Color backColor) + { + int backColorArgb = backColor.ToArgb(); + int maxWidth = bmp.Width; + int maxHeight = bmp.Height; + + //左側の空白部分を計測する + int leftPosition = -1; + for (int x = 0; x < maxWidth; x++) + { + for (int y = 0; y < maxHeight; y++) + { + //違う色を見つけたときは、位置を決定する + if (bmp.GetPixel(x, y).ToArgb() != backColorArgb) + { + leftPosition = x; + break; + } + } + if (0 <= leftPosition) + { + break; + } + } + //違う色が見つからなかった時 + if (leftPosition < 0) + { + return Rectangle.Empty; + } + + //右側の空白部分を計測する + int rightPosition = -1; + for (int x = maxWidth - 1; leftPosition < x; x--) + { + for (int y = 0; y < maxHeight; y++) + { + if (bmp.GetPixel(x, y).ToArgb() != backColorArgb) + { + rightPosition = x; + break; + } + } + if (0 <= rightPosition) + { + break; + } + } + if (rightPosition < 0) + { + rightPosition = leftPosition; + } + + //上の空白部分を計測する + int topPosition = -1; + for (int y = 0; y < maxHeight; y++) + { + for (int x = leftPosition; x <= rightPosition; x++) + { + if (bmp.GetPixel(x, y).ToArgb() != backColorArgb) + { + topPosition = y; + break; + } + } + if (0 <= topPosition) + { + break; + } + } + if (topPosition < 0) + { + return Rectangle.Empty; + } + + //下の空白部分を計測する + int bottomPosition = -1; + for (int y = maxHeight - 1; topPosition < y; y--) + { + for (int x = leftPosition; x <= rightPosition; x++) + { + if (bmp.GetPixel(x, y).ToArgb() != backColorArgb) + { + bottomPosition = y; + break; + } + } + if (0 <= bottomPosition) + { + break; + } + } + if (bottomPosition < 0) + { + bottomPosition = topPosition; + } + + //結果を返す + return new Rectangle(leftPosition, topPosition, + rightPosition - leftPosition, bottomPosition - topPosition); + } + + #endregion diff --git a/Crystallography/FindParameter.cs b/Crystallography/FindParameter.cs index c0551f0..bb90034 100644 --- a/Crystallography/FindParameter.cs +++ b/Crystallography/FindParameter.cs @@ -446,7 +446,7 @@ public void Clear() public void SetCoeff() { - Coeff = Geometriy.GetParameterOfCurveOfSecondaryDegree(points.ToArray()); + Coeff = Geometry.GetParameterOfCurveOfSecondaryDegree(points.ToArray()); } public override string ToString() diff --git a/Crystallography/Images/ImageIO.cs b/Crystallography/Images/ImageIO.cs index 19aba14..44bc5d8 100644 --- a/Crystallography/Images/ImageIO.cs +++ b/Crystallography/Images/ImageIO.cs @@ -1761,6 +1761,35 @@ public class IPAImage public WaveProperty WaveProperty; public double CameraLength; public double FilmBlur = 200; + + public IPAImage() + { + Intensity = []; + IntensityDouble = []; + Scale = 1; + Width = 1; + Height = 1; + Center = new PointD(0, 0); + Resolution = 1; + WaveProperty = new WaveProperty(29, XrayLine.Ka); + CameraLength = 1; + FilmBlur = 200; + } + + public IPAImage(double version, uint[] intensity, double[] intensityDouble, double scale, int width, int height, PointD center, double resolution, WaveProperty waveProperty, double cameraLength, double filmBlur) + { + Version = version; + Intensity = intensity; + IntensityDouble = intensityDouble; + Scale = scale; + Width = width; + Height = height; + Center = center; + Resolution = resolution; + WaveProperty = waveProperty; + CameraLength = cameraLength; + FilmBlur = filmBlur; + } // public uint[] ConvertTable = new uint[65536]; } } diff --git a/Crystallography/Images/ImageProcessor.cs b/Crystallography/Images/ImageProcessor.cs index 016b462..e540160 100644 --- a/Crystallography/Images/ImageProcessor.cs +++ b/Crystallography/Images/ImageProcessor.cs @@ -363,13 +363,13 @@ static public PointD[] GetLineProfile(IEnumerable<(double X, double Y, double Z) 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); + pts = Geometry.GetPolygonDividedByLine(pts, normal1.a, normal1.b, normal1.c); + pts = Geometry.GetPolygonDividedByLine(pts, normal2.a, normal2.b, normal2.c); + pts = Geometry.GetPolygonDividedByLine(pts, parallel1.a, parallel1.b, parallel1.c); + pts = Geometry.GetPolygonDividedByLine(pts, parallel2.a, parallel2.b, parallel2.c); if (pts.Length > 2) { - var a = Geometriy.GetPolygonalArea(pts); + var a = Geometry.GetPolygonalArea(pts); area += a; intensity += z * a; } diff --git a/Crystallography/Mathematics/Geometriy.cs b/Crystallography/Mathematics/Geometry.cs similarity index 99% rename from Crystallography/Mathematics/Geometriy.cs rename to Crystallography/Mathematics/Geometry.cs index 1f46dde..fe8f761 100644 --- a/Crystallography/Mathematics/Geometriy.cs +++ b/Crystallography/Mathematics/Geometry.cs @@ -9,9 +9,9 @@ namespace Crystallography; -public static class Geometriy +public static class Geometry { - static Geometriy() + static Geometry() { MathNet.Numerics.Control.TryUseNativeMKL(); } diff --git a/Crystallography/Miscellaneous.cs b/Crystallography/Miscellaneous.cs index bcd8c9d..920778b 100644 --- a/Crystallography/Miscellaneous.cs +++ b/Crystallography/Miscellaneous.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; +using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; @@ -108,6 +109,53 @@ public static bool IsDecimalPointComma public static (int Division, int Modulus) DivMod(int n, int m) => (n / m, n % m); + /// + /// ファイルが使用中かどうかをチェック + /// + /// + /// + public static bool isFileExistsAndLocked(string path) + { + if (File.Exists(path)) + { + FileStream stream = null; + + try + { + stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); + } + catch (DirectoryNotFoundException e) + { + return false; + } + catch (FileNotFoundException e) + { + return false; + } + catch (IOException e) + { + if (File.Exists(path)) + { + return true; + } + } + catch (Exception e) + { + return false; + } + finally + { + if (stream != null) + { + stream.Close(); + } + } + + return false; + } + + return false; + } } diff --git a/Crystallography/MonteCarlo.cs b/Crystallography/MonteCarlo.cs new file mode 100644 index 0000000..0ad4e26 --- /dev/null +++ b/Crystallography/MonteCarlo.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using V3 = OpenTK.Vector3d; +using M3 = OpenTK.Matrix3d; + +namespace Crystallography +{ + + //Electron beam-specimen interactions and simulation methods in microscopy 2018 + //Eqs (2.38), (2.41), (2.42) などを参考 + public class MonteCarlo + { + public static int seed = 0; + + public readonly double Z, A, ρ; + public readonly double InitialKev, Tilt; + public readonly double coeff1, coeff2, coeff3; + + public readonly double k, J, tan; + + public readonly double ThresholdKev; + + /// + /// コンストラクタ + /// + /// 原子番号 (単位無し) + /// 原子量 (g/mol) + /// 密度 (g/cm^3) + /// 入射電子エネルギー (kev) + /// 試料表面の傾き (rad, X軸で回転) + /// 飛程計算を打ち切るエネルギー (kev) + public MonteCarlo(double z, double a, double _ρ, double kev, double tilt, double thresholdKev = 2) + { + Z = z; + A = a; + Tilt = tilt; + ρ = _ρ; + InitialKev = kev; + Tilt = tilt; + ThresholdKev = thresholdKev; + + //トータル散乱断面積の計算中に出てくる定数 + coeff1 = Z * UniversalConstants.e0 * UniversalConstants.e0 / (8.0 * Math.PI * UniversalConstants.ε0); + //平均自由行程のところに出てくる定数 + coeff2 = A / UniversalConstants.A / ρ * 1E21;// / Math.PI; + //阻止能の計算中に出てくる定数 + coeff3 = -Z * UniversalConstants.A * ρ * 1E3 / (A * 1E-3) * Math.Pow(UniversalConstants.e0, 4) + / 4 / Math.PI / UniversalConstants.ε0 / UniversalConstants.ε0 / UniversalConstants.eV_joule * 1E-9 * 1E-3; + + //阻止能の計算中に出てくる物質依存の定数 k Joy and Luo (1989)によれば 6C:0.77, 13Al: 0.815, 14Si: 0.822, 28Ni: 0.83, 29Cu: 0.83, 47Ag:0.852, 79Au: 0.851 + //取りあえず対数近似した値を使う + k = 0.0299 * Math.Log(Z) + 0.7307; + //阻止能の計算中に出てくる物質依存の定数 J (eV) Z<=12の時は J=11.5evにするらしい (Joy&Luo 1989) + J = Z <= 12 ? 11.5 * Z : (9.76 * Z + 58.5 / Math.Pow(Z, 0.19)); + tan = Math.Tan(tilt); + } + + public (double ScreeningParameter, double CrossSection, double MeanFreePath, double StoppingPower) GetParameters(double kev) + { + //電子の質量 (kg) × 電子の速度の2乗 (m^2/s^2) + var mv2 = UniversalConstants.Convert.EnergyToElectronMass(kev) * UniversalConstants.Convert.EnergyToElectronVelositySquared(kev); + //散乱係数 + var α = 0.0034 * Math.Pow(Z, 2.0 / 3.0) / kev; + //トータル散乱断面積 (nm^2) + var t1 = coeff1 / mv2; + var σ_E = t1 * t1 * 4 * Math.PI / α / (α + 1) * 1E18; + //弾性散乱平均自由行程 (nm) + var λ_el = coeff2 / σ_E; + //阻止能 (Joy and Luo 1989) (kev/nm単位) + var sp = coeff3 / mv2 * Math.Log(1.166 * k + 0.583 * mv2 / UniversalConstants.eV_joule / J); + return (α, σ_E, λ_el, sp); + } + + /// + /// 電子線の飛程を計算する. 電子は -Z軸に沿って入射し、試料と(0,0,0)の座標で衝突したあと、thresholdで指定したエネルギーまで減衰するか、 + /// 試料表面を脱出するまでの飛程を計算する。返り値は、座標 p (µm単位)と エネルギー e (kev単位) のタプル配列 + /// + /// 返り値は、座標 p (µm単位)と エネルギー e (kev単位) のタプル配列 + public (V3 p, double e)[] GetTrajectories() + { + var r = new Random(Interlocked.Increment(ref seed)); + var trajectory = new List<(V3 p, double e)>() { (new V3(0, 0, 0), InitialKev) }; + var vec = new V3(0, 0, -1); + + //電子エネルギーがThresholdKev以下になるか、試料を脱出するまでループ + while (trajectory[^1].e > ThresholdKev && trajectory[^1].p.Y * tan >= trajectory[^1].p.Z) + { + //パラメーター取得 + var (α, _, λ_el, sp) = GetParameters(trajectory[^1].e); + //飛行距離 s + var s = -λ_el * Math.Log(r.NextDouble()); + if (trajectory.Count > 1) + { + double rnd2 = r.NextDouble(), rnd3 = r.NextDouble(); + double cosθ = 1 - 2 * α * rnd2 / (1 + α - rnd2), sinθ = Math.Sqrt(1 - cosθ * cosθ); + double φ = 2 * Math.PI * rnd3, cosφ = Math.Cos(φ), sinφ = Math.Sin(φ); + var rot = CreateRotationFromZ(vec); + vec = new V3( + rot.M11 * sinθ * cosφ + rot.M12 * sinθ * sinφ + rot.M13 * cosθ, + rot.M21 * sinθ * cosφ + rot.M22 * sinθ * sinφ + rot.M23 * cosθ, + rot.M31 * sinθ * cosφ + rot.M32 * sinθ * sinφ + rot.M33 * cosθ + ); + } + trajectory.Add((trajectory[^1].p + s * vec, trajectory[^1].e + s * sp)); + } + return trajectory.Select(e => (e.p / 1000, e.e)).ToArray(); + } + + /// + /// 電子線の飛程を計算する. 電子は -Z軸に沿って入射し、試料と(0,0,0)の座標で衝突したあと、thresholdで指定したエネルギーまで減衰するか、 + /// 試料表面を脱出するまでの飛程を計算する。返り値は、座標 p (µm単位)と エネルギー e (kev単位) のタプル配列 + /// + /// 返り値は、座標 p (µm単位)と エネルギー e (kev単位) のタプル配列 + public (V3 p, V3 v, double e) GetBackscatteredElectrons() + { + var r = new Random(Interlocked.Increment(ref seed)); + //var trajectory = new List<(V3 p, double e)>() { (new V3(0, 0, 0), InitialKev) }; + double e = InitialKev; + V3 pos = new(0, 0, 0), vec = new(0, 0, -1); + + //電子エネルギーがThresholdKev以下になるか、試料を脱出するまでループ + while (e > ThresholdKev && pos.Y * tan >= pos.Z) + { + //パラメーター取得 + var (α, _, λ_el, sp) = GetParameters(e); + //飛行距離 s + var s = -λ_el * Math.Log(r.NextDouble()); + if (e != InitialKev) + { + double rnd2 = r.NextDouble(), rnd3 = r.NextDouble(); + double cosθ = 1 - 2 * α * rnd2 / (1 + α - rnd2), sinθ = Math.Sqrt(1 - cosθ * cosθ); + double φ = 2 * Math.PI * rnd3, cosφ = Math.Cos(φ), sinφ = Math.Sin(φ); + var rot = CreateRotationFromZ(vec); + vec = new V3( + rot.M11 * sinθ * cosφ + rot.M12 * sinθ * sinφ + rot.M13 * cosθ, + rot.M21 * sinθ * cosφ + rot.M22 * sinθ * sinφ + rot.M23 * cosθ, + rot.M31 * sinθ * cosφ + rot.M32 * sinθ * sinφ + rot.M33 * cosθ + ); + } + var tmpPos = pos + s * vec; + if (tmpPos.Y * tan < tmpPos.Z) + break; + pos = tmpPos; + e += s * sp; + } + return (pos, vec, e); + } + + /// + /// Z軸(001)を引数のベクトルvに回転させる行列を生成する + /// + /// + /// + public static M3 CreateRotationFromZ(V3 v) + { + v.Normalize(); + if (Math.Abs(v.Z - 1) < Th) + return M3.Identity; + else if (Math.Abs(v.Z + 1) < Th) + return M3.CreateRotationX(Math.PI); + else + return M3.CreateFromAxisAngle(V3.Cross(v, Z_vector), V3.CalculateAngle(Z_vector, v)); + } + public static readonly V3 Z_vector = new(0, 0, 1); + public const double Th = 0.0000001; + + } +} diff --git a/Crystallography/Profile.cs b/Crystallography/Profile.cs index 665ce0a..9187245 100644 --- a/Crystallography/Profile.cs +++ b/Crystallography/Profile.cs @@ -324,7 +324,7 @@ public Profile Differential(int n) } #endregion - public PointD[][] GetPointsWithinRectangle(RectangleD rect) => Geometriy.GetPointsWithinRectangle(this.Pt, rect); + public PointD[][] GetPointsWithinRectangle(RectangleD rect) => Geometry.GetPointsWithinRectangle(this.Pt, rect); #region ToGSAS: GSAS形式に変換する /// diff --git a/Crystallography/Stereonet.cs b/Crystallography/Stereonet.cs index 0312485..ca5e04a 100644 --- a/Crystallography/Stereonet.cs +++ b/Crystallography/Stereonet.cs @@ -12,10 +12,10 @@ public static class Stereonet /// /// /// - public static PointD ConvertVectorToWulff(Vector3D vec) + public static PointD ConvertVectorToWulff(Vector3DBase vec) { if (vec == null) return new PointD(-100, -100); - var v = Vector3D.Normarize(vec); + var v = Vector3DBase.Normarize(vec); return v.Z >= -0.999999 ? new PointD(v.X / (1 + v.Z), v.Y / (1 + v.Z)) : new PointD(-100, -100); } @@ -30,4 +30,8 @@ public static PointD ConvertVectorToSchmidt(Vector3DBase vec) var v = Vector3DBase.Normarize(vec); return v.Z >= -0.999999 ? new PointD(v.X / Math.Sqrt(1 + v.Z), v.Y / Math.Sqrt(1 + v.Z)) : new PointD(-100, -100); } + + public static PointD ConvertVectorToSchmidt(OpenTK.Vector3d vec) + =>ConvertVectorToSchmidt(new Vector3DBase(vec.X, vec.Y, vec.Z)); + } \ No newline at end of file diff --git a/Crystallography/Symmetry/SymmetryOperation.cs b/Crystallography/Symmetry/SymmetryOperation.cs index 6c99a2c..1ff5a48 100644 --- a/Crystallography/Symmetry/SymmetryOperation.cs +++ b/Crystallography/Symmetry/SymmetryOperation.cs @@ -67,6 +67,8 @@ public SymmetryOperation(SymmetryOperation so, int seriesNumber) public (int H, int K, int L) ConvertPlaneIndex((int H, int K, int L) index) => ConvertPlaneIndex(index.H, index.K, index.L); + + public (int H, int K, int L) ConvertPlaneIndex(int h, int k, int l) { if (Order == 1) @@ -168,5 +170,113 @@ public SymmetryOperation(SymmetryOperation so, int seriesNumber) return Order > 0 ? p : (-p.H, -p.K, -p.L); } } + + #region h,k,lを整数から実数に拡張したテストコード + public (double H, double K, double L) ConvertPlaneIndex((double H, double K, double L) index) + => ConvertPlaneIndex(index.H, index.K, index.L); + + public (double H, double K, double L) ConvertPlaneIndex(double h, double k, double l) + { + if (Order == 1) + return (h, k, l); + else if (Order == -1) + return (-h, -k, -l); + else + { + (double H, double K, double L) p = (0, 0, 0); + + if (SymmetryStatic.NumArray[SeriesNumber][5] == 5 || SymmetryStatic.NumArray[SeriesNumber][5] == 6) + {//trigonalかHexagonalの場合 + if (SymmetryStatic.NumArray[SeriesNumber][2] == 1) + {//Hexaセッティングの時 + if (Math.Abs(Order) == 2) + { + p = Direction switch + { + (0, 0, 1) => (-h, -k, l), + (1, 0, 0) => (h, -h - k, -l), + (0, 1, 0) => (-h - k, k, -l), + (1, 1, 0) => (k, h, -l), + (1, -1, 0) => (-k, -h, -l), + (2, 1, 0) => (-h, h + k, -l), + (1, 2, 0) => (h + k, -k, -l), + _ => (0, 0, 0) + }; + } + else if (Math.Abs(Order) == 3) + { + if (Direction == (0, 0, 1)) + p = Sense ? (k, -h - k, l) : (-h - k, h, l); + } + else if (Math.Abs(Order) == 6) + { + if (Direction == (0, 0, 1)) + p = Sense ? (h + k, -h, l) : (-k, h + k, l); + } + } + else + {//Rhomboセッティングの時 + if (Math.Abs(Order) == 2) + { + p = Direction switch + { + (0, 1, -1) => (-h, -l, -k), + (-1, 0, 1) => (-l, -k, -h), + (1, -1, 0) => (-k, -h, -l), + _ => (0, 0, 0) + }; + } + else if (Math.Abs(Order) == 3) + { + if (Direction == (1, 1, 1)) + p = Sense ? (k, l, h) : (l, h, k); + } + } + } + else + {//trigonalでもHexagonalでもない場合 + if (Math.Abs(Order) == 2) + { + p = Direction switch + { + (1, 0, 0) => (h, -k, -l), + (0, 1, 0) => (-h, k, -l), + (0, 0, 1) => (-h, -k, l), + (0, 1, 1) => (-h, l, k), + (1, 0, 1) => (l, -k, h), + (1, 1, 0) => (k, h, -l), + (0, 1, -1) => (-h, -l, -k), + (-1, 0, 1) => (-l, -k, -h), + (1, -1, 0) => (-k, -h, -l), + _ => (0, 0, 0) + }; + } + else if (Math.Abs(Order) == 3) + { + p = Direction switch + { + (+1, +1, +1) => Sense ? (+k, +l, +h) : (+l, +h, +k), + (+1, -1, -1) => Sense ? (-k, +l, -h) : (-l, -h, +k), + (-1, +1, -1) => Sense ? (-k, -l, +h) : (+l, -h, -k), + (-1, -1, +1) => Sense ? (+k, -l, -h) : (-l, +h, -k), + _ => (0, 0, 0) + }; + } + else if (Math.Abs(Order) == 4) + { + p = Direction switch + { + (1, 0, 0) => Sense ? (h, l, -k) : (h, -l, k), + (0, 1, 0) => Sense ? (-l, k, h) : (l, k, -h), + (0, 0, 1) => Sense ? (k, -h, l) : (-k, h, l), + _ => (0, 0, 0) + }; + } + } + return Order > 0 ? p : (-p.H, -p.K, -p.L); + } + } + #endregion + #endregion } \ No newline at end of file diff --git a/Crystallography/UniversalConstants.cs b/Crystallography/UniversalConstants.cs index ba21ea7..88f544d 100644 --- a/Crystallography/UniversalConstants.cs +++ b/Crystallography/UniversalConstants.cs @@ -84,7 +84,7 @@ public static class UniversalConstants public enum LengthUnit { km, m, cm, mm, um, nm, pm, fm } /// - /// アボガドロ数 (g) + /// アボガドロ数 (1/mol) /// public const double A = 6.0221367E23; @@ -143,8 +143,57 @@ public enum LengthUnit { km, m, cm, mm, um, nm, pm, fm } /// public const double Ry = 13.60569253; + /// + /// 真空の誘電率 (permittivity) of vacuum ε0 (F/m = C^2×s^2 /kg/m^3 ) + /// c^2 = 1/ε0/μ0の関係がある。 + /// + public const double ε0 = 8.8541878188E-12; + + /// + /// 真空の透磁率 (permeability in vacuum) μ0 (N/A^2) + /// c^2 = 1/ε0/μ0の関係がある。 + /// + public const double μ0 = 1.25663706127E-6; + + + public static class Convert { + /// + /// エネルギー(kev)を与えて電子の速度(m/s)を返す + /// + /// + /// + public static double EnergyToElectronVelosity(in double kev) + { + //return c * Math.Sqrt(1 - 1 / Math.Pow(1 + e0 * kev * 1000 / m0 / c / c, 2)); + var tmp = 1 + kev * 0.0019569507450453425; + return c * Math.Sqrt(1 - 1 / tmp / tmp); + } + + /// + /// エネルギー(kev)を与えて電子の速度の2乗(m^2/s^2)を返す + /// + /// + /// + public static double EnergyToElectronVelositySquared(in double kev) + { + var tmp = 1 + kev * 0.0019569507450453425; + return c2 * (1 - 1 / tmp / tmp); + } + + /// + /// エネルギー(kev)を与えて電子の重量(kg)を返す + /// + /// + /// + public static double EnergyToElectronMass(in double kev) + { + //var r = EnergyToElectronVelosity(kev) / c; + //return m0 / Math.Sqrt(1 - r * r); + return m0 * (1 + kev * 0.0019569507450453425); + } + /// /// 中性子の速度(m/μs)を与えて波長(nm)を返す /// diff --git a/Crystallography/WaveProperty.cs b/Crystallography/WaveProperty.cs index 4a8396b..59a8336 100644 --- a/Crystallography/WaveProperty.cs +++ b/Crystallography/WaveProperty.cs @@ -40,6 +40,11 @@ public class WaveProperty /// public double Convergence = 0; + public WaveProperty() + { + + } + /// /// ///