//回折斑点のパターンから晶帯軸を探す 1枚の写真から Mode1 2辺と間の角度 public static ZoneAxis[] GetZoneAxis(Crystal cry, PhotoInformation photo, bool excludeEquivalence) { List <ZoneAxis> za = new List <ZoneAxis>(); if (!photo.Paintable) { return(za.ToArray()); } cry.SetPlanes( double.MaxValue, photo.IsTriangleMode ? Math.Min(Math.Min(photo.d1min, photo.d2min), photo.d3min) : Math.Min(photo.d1min, photo.d2min), false, false, false, false, 0, 0, 0); Plane[] plane = cry.Plane.ToArray(); for (int n1 = 0; n1 < plane.Length; n1++) { if (!excludeEquivalence || plane[n1].IsRootIndex) { if (plane[n1].d > photo.d1min && plane[n1].d < photo.d1max) { for (int n2 = 0; n2 < plane.Length; n2++) { if (plane[n2].d > photo.d2min && plane[n2].d < photo.d2max) { ZoneAxis tempZoneAxis = new ZoneAxis(cry, plane[n1], plane[n2], photo.Tilt1, photo.Tilt2); if ((photo.IsTriangleMode && tempZoneAxis.plane3.d > photo.d3min && tempZoneAxis.plane3.d < photo.d3max) || (!photo.IsTriangleMode && tempZoneAxis.Theta < photo.Theta + photo.theta_err && tempZoneAxis.Theta > photo.Theta - photo.theta_err)) { for (int z = 2; z <= Math.Abs(tempZoneAxis.u) || z <= Math.Abs(tempZoneAxis.v) || z <= Math.Abs(tempZoneAxis.w); z++)//最大公約数で割る { if ((tempZoneAxis.u % z == 0) && (tempZoneAxis.v % z == 0) && (tempZoneAxis.w % z == 0)) { tempZoneAxis.u = tempZoneAxis.u / z; tempZoneAxis.v = tempZoneAxis.v / z; tempZoneAxis.w = tempZoneAxis.w / z; z = 1; } } za.Add(tempZoneAxis); } } } } } } //excludeEquivalence==true のとき、zaの中で等価なものを削除する if (excludeEquivalence) { for (int i = 0; i < za.Count; i++) { for (int j = i + 1; j < za.Count; j++) { if (SymmetryStatic.CheckEquivalentAxes(za[i].u, za[i].v, za[i].w, za[j].u, za[j].v, za[j].w, cry.Symmetry)) { if (za[i].plane1.h == za[j].plane1.h && za[i].plane1.k == za[j].plane1.k && za[i].plane1.l == za[j].plane1.l) { if (SymmetryStatic.CheckEquivalentPlanes(za[i].plane2.h, za[i].plane2.k, za[i].plane2.l, za[j].plane2.h, za[j].plane2.k, za[j].plane2.l, cry.Symmetry)) { za.RemoveAt(j); j--; } } } } } } return(za.ToArray()); }
//za1がtilt1,azimuth1に、za2がtilt2,azimuth2に、za3がなるべくtilt3,azimuth3に一致するようなオイラー角を返す public static Matrix3D SerchEulerAngleFromZoneAxes(ZoneAxis za1, ZoneAxis za2, ZoneAxis za3, Crystal cry) { double tilt1 = za1.tilt1; double azimuth1 = za1.tilt2; double tilt2 = za2.tilt1; double azimuth2 = za2.tilt2; double tilt3 = za3.tilt1; double azimuth3 = za3.tilt2; Vector3D v1 = Vector3D.Normarize(za1.u * cry.A_Axis + za1.v * cry.B_Axis + za1.w * cry.C_Axis); Vector3D v2 = Vector3D.Normarize(za2.u * cry.A_Axis + za2.v * cry.B_Axis + za2.w * cry.C_Axis); Vector3D v3 = Vector3D.Normarize(za3.u * cry.A_Axis + za3.v * cry.B_Axis + za3.w * cry.C_Axis); Vector3D V1 = new Vector3D(-Math.Sin(tilt1), -Math.Cos(tilt1) * Math.Sin(azimuth1), Math.Cos(tilt1) * Math.Cos(azimuth1)); Vector3D V2 = new Vector3D(-Math.Sin(tilt2), -Math.Cos(tilt2) * Math.Sin(azimuth2), Math.Cos(tilt2) * Math.Cos(azimuth2)); Vector3D V3 = new Vector3D(-Math.Sin(tilt3), -Math.Cos(tilt3) * Math.Sin(azimuth3), Math.Cos(tilt3) * Math.Cos(azimuth3)); double Phi, phi1, phi2, PhiStart, PhiEnd, phi1Start, phi1End, phi2Start, phi2End, step, PhiBest, phi1Best, phi2Best; double dev, devTemp; PhiStart = phi1Start = phi2Start = -Math.PI; PhiEnd = phi1End = phi2End = Math.PI * 1.001; Matrix3D m; step = Math.PI / 36.0; dev = double.PositiveInfinity; PhiBest = double.PositiveInfinity; phi1Best = double.PositiveInfinity; phi2Best = double.PositiveInfinity; double cosP, sinP, cosP1, sinP1, cosP2, sinP2; for (int n = 0; n < 25; n++) { for (Phi = PhiStart; Phi <= PhiEnd; Phi += step) { for (phi1 = phi1Start; phi1 <= phi1End; phi1 += step) { for (phi2 = phi2Start; phi2 <= phi2End; phi2 += step) { cosP = Math.Cos(Phi); sinP = Math.Sin(Phi); cosP1 = Math.Cos(phi1); sinP1 = Math.Sin(phi1); cosP2 = Math.Cos(phi2); sinP2 = Math.Sin(phi2); m = new Matrix3D( cosP2 * cosP1 - cosP * sinP1 * sinP2, -sinP2 * cosP1 - cosP * sinP1 * cosP2, sinP * sinP1, cosP2 * sinP1 + cosP * cosP1 * sinP2, -sinP2 * sinP1 + cosP * cosP1 * cosP2, -sinP * cosP1, sinP2 * sinP, cosP2 * sinP, cosP ); devTemp = (m * v1 - V1).Length2 + (m * v2 - V2).Length2 + (m * v3 - V3).Length2; if (dev > devTemp) { dev = devTemp; PhiBest = Phi; phi1Best = phi1; phi2Best = phi2; } } } } if (double.IsInfinity(PhiBest)) { break; } PhiStart = PhiBest - 2.5 * step; PhiEnd = PhiBest + 2.5 * step; phi1Start = phi1Best - 2.5 * step; phi1End = phi1Best + 2.5 * step; phi2Start = phi2Best - 2.5 * step; phi2End = phi2Best + 2.5 * step; step *= 0.4; } if (phi1Best < -Math.PI) { phi1Best += 2 * Math.PI; } if (phi1Best > Math.PI) { phi1Best -= 2 * Math.PI; } if (phi2Best < -Math.PI) { phi2Best += 2 * Math.PI; } if (phi2Best > Math.PI) { phi2Best -= 2 * Math.PI; } if (PhiBest < -Math.PI) { PhiBest += 2 * Math.PI; } if (PhiBest > Math.PI) { PhiBest -= 2 * Math.PI; } if (PhiBest < 0) { PhiBest = -PhiBest; if (phi1Best < 0) { phi1Best += Math.PI; } else { phi1Best -= Math.PI; } if (phi2Best < 0) { phi2Best += Math.PI; } else { phi2Best -= Math.PI; } } cosP = Math.Cos(PhiBest); sinP = Math.Sin(PhiBest); cosP1 = Math.Cos(phi1Best); sinP1 = Math.Sin(phi1Best); cosP2 = Math.Cos(phi2Best); sinP2 = Math.Sin(phi2Best); return(new Matrix3D( cosP2 * cosP1 - cosP * sinP1 * sinP2, -sinP2 * cosP1 - cosP * sinP1 * cosP2, sinP * sinP1, cosP2 * sinP1 + cosP * cosP1 * sinP2, -sinP2 * sinP1 + cosP * cosP1 * cosP2, -sinP * cosP1, sinP2 * sinP, cosP2 * sinP, cosP )); }