PageRenderTime 38ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/fpFormat/FormatModule/Gm.cs

https://bitbucket.org/kinna/itadp033_kucher_inna
C# | 3645 lines | 2872 code | 432 blank | 341 comment | 350 complexity | 728b2e2b912305f0d0cb73da19a31272 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #define L_ARM
  2. using System;
  3. using System.Data.SqlTypes;
  4. using System.Collections.Generic;
  5. using System.Collections;
  6. using Microsoft.SqlServer.Server;
  7. using System.Runtime.Serialization;
  8. using SoftServe.TaskElementary.FormatModule;
  9. namespace geometry
  10. {
  11. public static class Gm
  12. {
  13. public enum DecartPosition
  14. {
  15. Origin = 0,
  16. At1 = 1,
  17. At2 = 2,
  18. At3 = 3,
  19. At4 = 4,
  20. AtX_PlusY = 5,
  21. AtX_MinusY = 6,
  22. AtY_PlusX = 7,
  23. AtY_MinusX = 8
  24. }
  25. #region Common
  26. public static double Accuracy { get { return 0.0000001; } }
  27. public static uint MaxDigits { get { return 7; } }
  28. public static bool ApproximatelyEqual(double d1, double d2, double tol)
  29. {
  30. return (Math.Abs(d1 - d2) < tol);
  31. }
  32. public static bool ApproximatelyEqual(double d1, double d2)
  33. {
  34. return (Math.Abs(d1 - d2) < Accuracy);
  35. }
  36. public static bool ApproximatelyEqual(float d1, float d2, float tol)
  37. {
  38. return (Math.Abs(d1 - d2) < tol);
  39. }
  40. public static bool ApproximatelyEqual(float d1, float d2)
  41. {
  42. return (Math.Abs(d1 - d2) < Accuracy);
  43. }
  44. public static bool Factor(uint digits, out double factor1, out double factor2)
  45. {
  46. factor1 = 1;
  47. factor2 = 1;
  48. if (digits > MaxDigits)
  49. throw new ArgumentException("Argument exception: digits");
  50. switch (digits)
  51. {
  52. case 0:
  53. factor1 = factor2 = 0;
  54. return true;
  55. case 1:
  56. factor1 = 0.1;
  57. factor2 = 10;
  58. break;
  59. case 2:
  60. factor1 = 0.01;
  61. factor2 = 100;
  62. break;
  63. case 3:
  64. factor1 = 0.001;
  65. factor2 = 1000;
  66. break;
  67. case 4:
  68. factor1 = 0.0001;
  69. factor2 = 10000;
  70. break;
  71. case 5:
  72. factor1 = 0.00001;
  73. factor2 = 100000;
  74. break;
  75. default:
  76. for (int i = 0; i < digits; i++)
  77. {
  78. factor1 *= 0.1;
  79. factor2 *= 10;
  80. }
  81. break;
  82. }
  83. return false;
  84. }
  85. public static bool Factor(uint digits, out float factor1, out float factor2)
  86. {
  87. factor1 = 1;
  88. factor2 = 1;
  89. if (digits > MaxDigits)
  90. throw new ArgumentException("Argument exception: digits");
  91. switch (digits)
  92. {
  93. case 0:
  94. factor1 = factor2 = 0f;
  95. return true;
  96. case 1:
  97. factor1 = 0.1f;
  98. factor2 = 10f;
  99. break;
  100. case 2:
  101. factor1 = 0.01f;
  102. factor2 = 100f;
  103. break;
  104. case 3:
  105. factor1 = 0.001f;
  106. factor2 = 1000f;
  107. break;
  108. case 4:
  109. factor1 = 0.0001f;
  110. factor2 = 10000f;
  111. break;
  112. case 5:
  113. factor1 = 0.00001f;
  114. factor2 = 100000f;
  115. break;
  116. default:
  117. for (int i = 0; i < digits; i++)
  118. {
  119. factor1 *= 0.1f;
  120. factor2 *= 10f;
  121. }
  122. break;
  123. }
  124. return false;
  125. }
  126. public static double DegToRad(float angle) { return angle * Math.PI / 180; }
  127. public static double DegToRad(double angle) { return angle * Math.PI / 180; }
  128. public static double RadToDeg(float angle) { return angle * 180 / Math.PI; }
  129. public static double RadToDeg(double angle) { return angle * 180/ Math.PI; }
  130. public static double RoundTo(float value, uint digits)
  131. {
  132. float factor1 = default(float);
  133. float factor2 = factor1;
  134. float ret;
  135. Factor(digits, out factor1, out factor2);
  136. if (Factor(digits, out factor1, out factor2))
  137. ret = (int)value;
  138. else
  139. ret = ((int)(value * factor2)) * factor1;
  140. return ret;
  141. }
  142. public static double RoundTo(double value, uint digits)
  143. {
  144. double factor1 = default(double);
  145. double factor2 = factor1;
  146. double ret;
  147. Factor(digits, out factor1, out factor2);
  148. if (Factor(digits, out factor1, out factor2))
  149. ret = (int)value;
  150. else
  151. ret = ((int)(value * factor2)) * factor1;
  152. return ret;
  153. }
  154. public static Vector RoundTo(Vector value, uint digits)
  155. {
  156. double factor1 = default(double);
  157. double factor2 = factor1;
  158. Vector ret = new Vector();
  159. if (Factor(digits, out factor1, out factor2))
  160. {
  161. ret.x = (int)value.x;
  162. ret.y = (int)value.y;
  163. ret.z = (int)value.z;
  164. }
  165. else
  166. {
  167. ret.x = ((int)(value.x * factor2)) * factor1;
  168. ret.y = ((int)(value.y * factor2)) * factor1;
  169. ret.z = ((int)(value.z * factor2)) * factor1;
  170. }
  171. return ret;
  172. }
  173. public static Point RoundTo(Point value, uint digits)
  174. {
  175. double factor1 = default(double);
  176. double factor2 = factor1;
  177. Point ret = new Point();
  178. Factor(digits, out factor1, out factor2);
  179. if (Factor(digits, out factor1, out factor2))
  180. {
  181. ret.x = (int)value.x;
  182. ret.y = (int)value.y;
  183. ret.z = (int)value.z;
  184. }
  185. else
  186. {
  187. ret.x = ((int)(value.x * factor2)) * factor1;
  188. ret.y = ((int)(value.y * factor2)) * factor1;
  189. ret.z = ((int)(value.z * factor2)) * factor1;
  190. }
  191. return ret;
  192. }
  193. public static Quaterion RoundTo(Quaterion value, uint digits)
  194. {
  195. double factor1 = default(double);
  196. double factor2 = factor1;
  197. Quaterion ret = new Quaterion();
  198. Factor(digits, out factor1, out factor2);
  199. if (Factor(digits, out factor1, out factor2))
  200. {
  201. ret.Vector = new Vector((int)value.Vector.x, (int)value.Vector.y, (int)value.Vector.z);
  202. ret.W = (int)value.W;
  203. }
  204. else
  205. {
  206. ret.Vector = new Vector(((int)(value.Vector.x * factor2)) * factor1, ((int)(value.Vector.y * factor2)) * factor1, ((int)(value.Vector.z * factor2)) * factor1);
  207. ret.W = ((int)(value.W * factor2)) * factor1;
  208. }
  209. return ret;
  210. }
  211. public static Matrix3 RoundTo(Matrix3 value, uint digits)
  212. {
  213. double factor1 = default(double);
  214. double factor2 = factor1;
  215. double[] data = value.Data;
  216. //Matrix3 ret = new Matrix3();
  217. Factor(digits, out factor1, out factor2);
  218. if (Factor(digits, out factor1, out factor2))
  219. {
  220. for (int i = 0; i < data.Length; i++)
  221. data[i] = (int)data[i];
  222. }
  223. else
  224. {
  225. for (int i = 0; i < data.Length; i++)
  226. data[i] = ((int)(data[i] * factor2)) * factor1;
  227. }
  228. return new Matrix3(data);
  229. }
  230. public static Transform RoundTo(Transform value, uint digits)
  231. {
  232. double factor1 = default(double);
  233. double factor2 = factor1;
  234. double[] data = value.Data;
  235. Transform ret = new Transform();
  236. Factor(digits, out factor1, out factor2);
  237. if (Factor(digits, out factor1, out factor2))
  238. {
  239. for (int i = 0; i < data.Length; i++)
  240. data[i] = (int)data[i];
  241. }
  242. else
  243. {
  244. for (int i = 0; i < data.Length; i++)
  245. data[i] = ((int)(data[i] * factor2)) * factor1;
  246. }
  247. return new Transform(data);
  248. }
  249. /// <summary>
  250. /// Split double array to vectors
  251. /// </summary>
  252. /// <param name="values"></param>
  253. /// <param name="vDim"></param>
  254. /// <param name="useRound"></param>
  255. /// <param name="digits"></param>
  256. /// <returns></returns>
  257. public static Vector[] SplitToVectors(double[] values, byte vDim, bool useRound, uint digits)
  258. {
  259. int vCCount = values.Length % vDim;
  260. if (vDim < 2 | vDim > 3)
  261. throw new ArgumentException("Gm.SplitToVectors: vDim must be 2 or 3");
  262. if (vCCount > 0 & vCCount < vDim - 1)
  263. throw new ArgumentException("Gm.SplitToVectors: values");
  264. Vector[] ret = new Vector[(int)(values.Length / vDim) + (vCCount > 0 ? 1 : 0)];
  265. for (int i = 0, counter = 0; i < values.Length & counter < ret.Length; i += vDim, counter++)
  266. {
  267. if (vDim > 1)
  268. {
  269. ret[counter].x = values[i];
  270. ret[counter].y = values[i + 1];
  271. }
  272. if (vDim > 2 && i + 2 < values.Length)
  273. ret[counter].z = values[i + 2];
  274. // round
  275. if (useRound)
  276. ret[counter].Round(digits);
  277. }
  278. return ret;
  279. }
  280. /// <summary>
  281. /// Split double array to points
  282. /// </summary>
  283. /// <param name="values"></param>
  284. /// <param name="vDim"></param>
  285. /// <param name="useRound"></param>
  286. /// <param name="digits"></param>
  287. /// <returns></returns>
  288. public static Point[] SplitToPoints(double[] values, byte vDim, bool useRound, uint digits)
  289. {
  290. int vCCount = values.Length % vDim;
  291. if (vDim < 2 | vDim > 4)
  292. throw new ArgumentException("Gm.SplitToPoints: vDim must be 2 or 3");
  293. if (vCCount > 0 & vCCount < vDim - 1)
  294. throw new ArgumentException("Gm.SplitToPoints: values");
  295. Point[] ret = new Point[(int)(values.Length / vDim) + (vCCount > 0 ? 1 : 0)];
  296. for (int i = 0, counter = 0; i < values.Length & counter < ret.Length; i += vDim, counter++)
  297. {
  298. if (vDim > 1)
  299. {
  300. ret[counter].x = values[i];
  301. ret[counter].y = values[i + 1];
  302. }
  303. if (vDim > 2 && i + 2 < values.Length)
  304. ret[counter].z = values[i + 2];
  305. // uses round
  306. if (useRound)
  307. ret[counter].Round(digits);
  308. }
  309. return ret;
  310. }
  311. /// <summary>
  312. /// Split double array to points
  313. /// </summary>
  314. /// <param name="values"></param>
  315. /// <param name="vDim"></param>
  316. /// <param name="useRound"></param>
  317. /// <param name="digits"></param>
  318. /// <returns></returns>
  319. public static Point[] SplitToPoints(float[] values, byte vDim, bool useRound, uint digits)
  320. {
  321. int vCCount = values.Length % vDim;
  322. if (vDim < 2 | vDim > 4)
  323. throw new ArgumentException("Gm.SplitToPoints: vDim must be 2 or 3");
  324. if (vCCount > 0 & vCCount < vDim - 1)
  325. throw new ArgumentException("Gm.SplitToPoints: values");
  326. Point[] ret = new Point[(int)(values.Length / vDim) + (vCCount > 0 ? 1 : 0)];
  327. for (int i = 0, counter = 0; i < values.Length & counter < ret.Length; i += vDim, counter++)
  328. {
  329. if (vDim > 1)
  330. {
  331. ret[counter].x = values[i];
  332. ret[counter].y = values[i + 1];
  333. }
  334. if (vDim > 2 && i + 2 < values.Length)
  335. ret[counter].z = values[i + 2];
  336. // uses round
  337. if (useRound)
  338. ret[counter].Round(digits);
  339. }
  340. return ret;
  341. }
  342. public static double GetPolarAngle02P(double x, double y)
  343. {
  344. return Math.Atan(y / (x * x + y * y));
  345. }
  346. public static double iLeftOrRight(Point p, Point p1, Point p2)
  347. {
  348. double result = (p1.x - p.x) * (p2.y - p.y) - (p2.x - p.x) * (p1.y - p.y);
  349. if (Math.Abs(result) < Accuracy * Accuracy)
  350. result = 0;
  351. return result;
  352. }
  353. public static double SignTriangSquare(Point p1, Point p2, Point p3, bool isClockWice)
  354. {
  355. /*
  356. // p1, p2, p3
  357. -------
  358. x1 y1 1
  359. x2 y2 1
  360. x3 y3 1
  361. -------
  362. return m_matrix[0, 0] * m_matrix[1, 1] * m_matrix[2, 2] + m_matrix[0, 1] * m_matrix[1, 2] * m_matrix[2, 0] + m_matrix[0, 2] * m_matrix[1, 0] * m_matrix[2, 1]
  363. - m_matrix[0, 2] * m_matrix[1, 1] * m_matrix[2, 0] - m_matrix[0, 1] * m_matrix[1, 0] * m_matrix[2, 2] - m_matrix[0, 0] * m_matrix[1, 2] * m_matrix[2, 1];
  364. */
  365. double result = p1.x * p2.y + p1.y * p3.x + p2.x * p3.y - p2.y * p3.x - p1.y * p2.x - p1.x * p3.y;
  366. return isClockWice ? -result : result;
  367. }
  368. public static Point Mid(Point p1, Point p2)
  369. {
  370. double
  371. x = (p1.x + p2.x) / 2,
  372. y = (p1.y + p2.y) / 2,
  373. z = (p1.z + p2.z) / 2;
  374. return new Point(x, y, z);
  375. }
  376. public static bool DetectTriang(IEnumerable<Point> points,
  377. out Point p1, out Point p2, out Point p3)
  378. {
  379. ///Set points to default
  380. ///
  381. p1 = default(Point);
  382. p2 = default(Point);
  383. p3 = default(Point);
  384. /// Preparation
  385. ///
  386. IEnumerator<Point> iEnum = null;
  387. if (points == null)
  388. return false;
  389. if ((iEnum = points.GetEnumerator()) == null)
  390. return false;
  391. iEnum.Reset();
  392. ///Read first two points
  393. ///
  394. if (iEnum.MoveNext())
  395. p1 = iEnum.Current;
  396. else
  397. return false;
  398. if (iEnum.MoveNext())
  399. p2 = iEnum.Current;
  400. else
  401. return false;
  402. /// Search point
  403. ///
  404. while (iEnum.MoveNext())
  405. {
  406. if ( Math.Abs( iLeftOrRight(iEnum.Current, p1, p2)) > Accuracy)
  407. {
  408. p3 = iEnum.Current;
  409. return true;
  410. }
  411. }
  412. return false;
  413. }
  414. public static Point Centroid(IEnumerable<Point> points, out bool isDetect)
  415. {
  416. Point ret = default(Point),
  417. p1 = default(Point), p2 = default(Point), p3 = default(Point);
  418. isDetect = false;
  419. if (DetectTriang(points, out p1, out p2, out p3))
  420. {
  421. Point m1 = Mid(p2, p3);
  422. Point m2 = Mid(p1, p3);
  423. Point m3 = Mid(p1, p2);
  424. if (Intersect(p1, m1, p2, m2, out ret) < 1)
  425. {
  426. ret = default(Point);
  427. isDetect = false;
  428. }
  429. isDetect = true;
  430. }
  431. return ret;
  432. }
  433. public static void Sort(ref Point[] array, int minIndex, int maxIndex)
  434. {
  435. Dictionary<bool, List<Point>> convSegment = new Dictionary<bool, List<Point>>();
  436. /// up convex
  437. ///
  438. convSegment.Add(false, new List<Point>());
  439. /// down convex
  440. ///
  441. convSegment.Add(true, new List<Point>());
  442. for (int i = 0; i < array.Length; i++)
  443. {
  444. double res = Gm.iLeftOrRight(array[i], array[minIndex], array[maxIndex]);
  445. if (Math.Abs(res) < Accuracy)
  446. continue;
  447. if (res > 0)
  448. convSegment[false].Add(array[i]);
  449. else
  450. convSegment[true].Add(array[i]);
  451. }
  452. }
  453. public static bool Convex(ref Point[] tPoints)
  454. {
  455. int minIndex = 0, maxIndex = 0, tIndex = 0;
  456. double temp = 0;
  457. //double max = 0;
  458. //double min = 0;
  459. //if (tPoints.Length > 0)
  460. //{
  461. // min = tPoints[0].x;
  462. // max = tPoints[0].x;
  463. //}
  464. /// loock for min index and max index by x-componenta
  465. ///
  466. for (int i = 0; i < tPoints.Length; i++)
  467. {
  468. //if (min > tPoints[i].x)
  469. //{
  470. // min = tPoints[i].x;
  471. // minIndex = i;
  472. //}
  473. //if (max < tPoints[i].x)
  474. //{
  475. // max = tPoints[i].x;
  476. // maxIndex = i;
  477. //}
  478. System.Diagnostics.Debug.Print("x{0:F4}; y{1:F4}; z{2:F4};", new object[] { tPoints[i].x, tPoints[i].y, tPoints[i].z });
  479. if (tPoints[minIndex].x > tPoints[i].x)
  480. minIndex = i;
  481. if (tPoints[maxIndex].x < tPoints[i].x)
  482. maxIndex = i;
  483. }
  484. double tSquare = 0;
  485. /// Look for point with max triange square
  486. ///
  487. for (int i = 0; i < tPoints.Length; i++)
  488. {
  489. temp = Gm.TriangSquareGeron(tPoints[minIndex], tPoints[maxIndex], tPoints[i]);
  490. if (Math.Abs(tSquare)< Math.Abs(temp))
  491. {
  492. tSquare = temp;
  493. tIndex = i;
  494. }
  495. }
  496. bool isDetect = false;
  497. Point cPoint = Centroid(new Point[] { tPoints[minIndex], tPoints[maxIndex], tPoints[tIndex] }, out isDetect);
  498. /// projected face is line
  499. ///
  500. if (!isDetect)
  501. return false;
  502. /// projected face is polygon
  503. /// Sort points as polar angles
  504. ///
  505. Sort(ref tPoints, minIndex, maxIndex);
  506. return true;
  507. }
  508. public static void JoinConvex(ref List<Point> resultConvex, ref List<Point> convex1, ref List<Point> convex2)
  509. {
  510. }
  511. public static double Length2(Point p1, Point p2)
  512. {
  513. return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z);
  514. }
  515. public static double TriangSquareGeron(Point p1, Point p2, Point p3)
  516. {
  517. double a = Math.Sqrt(Length2(p1, p2));
  518. double b = Math.Sqrt(Length2(p2, p3));
  519. double c = Math.Sqrt(Length2(p1, p3));
  520. double p = 0.5 * (a + b + c);
  521. return p * Math.Sqrt((p - a) * (p - b) * (p - c));
  522. }
  523. public static double TriangSquare(Point p1, Point p2, Point p3)
  524. {
  525. return 0.5 * Math.Abs(SignTriangSquare(p1, p2, p3, false));
  526. }
  527. public static int Intersect(Point a1, Point a2, Point b1, Point b2, out Point intersection)
  528. {
  529. intersection = default(Point);
  530. double
  531. d = (a1.x - a2.x) * (b2.y - b1.y) - (a1.y - a2.y) * (b2.x - b1.x),
  532. da = (a1.x - b1.x) * (b2.y - b1.y) - (a1.y - b1.y) * (b2.x - b1.x),
  533. db = (a1.x - a2.x) * (a1.y - b1.y) - (a1.y - a2.y) * (a1.x - b1.x);
  534. if (Math.Abs(d) < Accuracy)
  535. return 0;
  536. double
  537. ta = da / d,
  538. tb = db / d;
  539. if (0 <= ta & ta <= 1 & 0 <= tb & tb <= 1)
  540. {
  541. intersection = new Point(a1.x + ta * (a2.x - a1.x), a1.y + ta * (a2.y - a1.y), 0);
  542. return 1;
  543. }
  544. return -1;
  545. }
  546. #endregion
  547. #region Vector definition
  548. //[System.Diagnostics.DebuggerDisplay("{format(4)}", Name = "Vector")]
  549. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  550. public struct Vector : INullable, IEquatable<Vector>
  551. {
  552. public double x;
  553. public double y;
  554. public double z;
  555. private bool m_null;
  556. private string format(byte dig)
  557. {
  558. Vector v = RoundTo(this,dig);
  559. return "(" + v.x.ToString() + "; " + v.y.ToString() + "; " + v.z.ToString() + "), Length:" + v.Length().ToString();
  560. }
  561. public Vector(double x, double y, double z)
  562. : this()
  563. {
  564. this.x = x;
  565. this.y = y;
  566. this.z = z;
  567. }
  568. public Vector(double[] points)
  569. : this()
  570. {
  571. if (points != null && points.Length >= 2)
  572. {
  573. this.x = points[0];
  574. this.y = points[1];
  575. if (points.Length > 2)
  576. this.z = points[2];
  577. }
  578. else
  579. throw new ArgumentOutOfRangeException("Array size have to be equal or greater than 3 elements");
  580. }
  581. public Vector(Vector v)
  582. : this()
  583. {
  584. this.x = v.x;
  585. this.y = v.y;
  586. this.z = v.z;
  587. }
  588. public void SetCoords(double x, double y, double z)
  589. {
  590. this.x = x;
  591. this.y = y;
  592. this.z = z;
  593. }
  594. public void SetCoords(Vector v)
  595. {
  596. this.x = v.x;
  597. this.y = v.y;
  598. this.z = v.z;
  599. }
  600. public void SetCoords(double[] points)
  601. {
  602. if (points != null && points.Length >= 2)
  603. {
  604. this.x = points[0];
  605. this.y = points[1];
  606. if (points.Length >= 3)
  607. this.z = points[2];
  608. }
  609. else
  610. throw new ArgumentOutOfRangeException("Array size have to be equal or greater than 3 elements");
  611. }
  612. public void Normalize()
  613. {
  614. double dist = Length2();
  615. if (dist > 0)
  616. {
  617. x /= dist;
  618. y /= dist;
  619. z /= dist;
  620. }
  621. }
  622. public Vector GetNormalized()
  623. {
  624. Vector v = new Vector(x, y, z);
  625. double dist = v.Length();
  626. if (dist > 0)
  627. {
  628. dist = 1 / dist;
  629. v.x *= dist;
  630. v.y *= dist;
  631. v.z *= dist;
  632. }
  633. return v;
  634. }
  635. /// <summary>
  636. /// Creates parallel vector, at point
  637. /// </summary>
  638. /// <param name="point"></param>
  639. /// <returns></returns>
  640. public Vector GetParallel(Point point)
  641. {
  642. Vector v = this;
  643. v.x += point.x;
  644. v.y += point.y;
  645. v.z += point.z;
  646. return v;
  647. }
  648. /// <summary>
  649. /// Creates parallel vector, at point
  650. /// </summary>
  651. /// <param name="point"></param>
  652. /// <returns></returns>
  653. public Vector GetParallel(double distance)
  654. {
  655. Vector normal = GetPerpVector()*distance;
  656. Vector v = normal.GetPerpVector();
  657. if (this.GetNormalized() != v)
  658. v.Inverce();
  659. return v;
  660. }
  661. /// <summary>
  662. /// Returns perpendicular vector
  663. /// </summary>
  664. /// <returns></returns>
  665. public Vector GetPerpVector()
  666. {
  667. if ((AngleTo(new Vector(0, 1, 0)) < Accuracy) || (AngleTo(new Vector(0, -1, 0)) < Accuracy))
  668. {
  669. return new Vector(y, 0, 0).GetNormalized();
  670. }
  671. return new Vector(z, 0, -x).GetNormalized();
  672. }
  673. public void Inverce() { x = -x; y = -y; z = -z; }
  674. /// <summary>
  675. /// Returns opposite vector
  676. /// </summary>
  677. /// <returns></returns>
  678. public Vector GetInverse()
  679. {
  680. return new Vector(-x, -y, -z);
  681. }
  682. public double Length()
  683. {
  684. return Math.Sqrt(x * x + y * y + z * z);
  685. }
  686. public double Length2()
  687. {
  688. return x * x + y * y + z * z;
  689. }
  690. public Vector Rotate(Vector dir, double ang)
  691. {
  692. if (ang == 0)
  693. return this;
  694. double c, s;
  695. double a;
  696. a = ang * Math.PI / 180;
  697. c = Math.Cos(a);
  698. s = Math.Sin(a);
  699. if (Double.IsNaN(c))
  700. c = 0;
  701. if (Double.IsNaN(s))
  702. s = 0;
  703. double nx, ny, nz;
  704. nx = x * (c + (1 - c) * (dir.x * dir.x)) + y * ((1 - c) * dir.y * dir.x + s * dir.z) + z * ((1 - c) * dir.z * dir.x - s * dir.y);
  705. ny = x * ((1 - c) * dir.y * dir.x - s * dir.z) + y * (c + (1 - c) * (dir.y * dir.y)) + z * ((1 - c) * dir.z * dir.y + s * dir.x);
  706. nz = x * ((1 - c) * dir.z * dir.x + s * dir.y) + y * ((1 - c) * dir.z * dir.y - s * dir.x) + z * (c + (1 - c) * (dir.z * dir.z));
  707. x = nx;
  708. y = ny;
  709. z = nz;
  710. return this;
  711. }
  712. public void Round(uint digits)
  713. {
  714. double factor1 = default(double);
  715. double factor2 = factor1;
  716. Factor(digits, out factor1, out factor2);
  717. if (Factor(digits, out factor1, out factor2))
  718. {
  719. x = (int)x;
  720. y = (int)y;
  721. z = (int)z;
  722. }
  723. else
  724. {
  725. x = ((int)(x * factor2)) * factor1;
  726. y = ((int)(y * factor2)) * factor1;
  727. z = ((int)(z * factor2)) * factor1;
  728. }
  729. }
  730. public double AngleTo(Vector vector)
  731. {
  732. if (vector.Length() == 0)
  733. return 0;
  734. double d = (this * vector) / (Length() * vector.Length());
  735. if (ApproximatelyEqual(d, 1, Accuracy))
  736. {
  737. d = 1;
  738. }
  739. else if (ApproximatelyEqual(d, -1, Accuracy))
  740. {
  741. d = -1;
  742. }
  743. return Math.Acos(d);
  744. }
  745. public double AngleToNonACos(Vector vector)
  746. {
  747. if (vector.Length() == 0)
  748. return 0;
  749. double d = (this * vector) / (Length() * vector.Length());
  750. if (ApproximatelyEqual(d, 1, Accuracy))
  751. {
  752. d = 1;
  753. }
  754. else if (ApproximatelyEqual(d, -1, Accuracy))
  755. {
  756. d = -1;
  757. }
  758. return d;
  759. }
  760. public bool IsParallelTo(Vector vector)
  761. {
  762. double angle = AngleTo(vector);
  763. return (ApproximatelyEqual(angle, 0, Accuracy) || ApproximatelyEqual(angle, Math.PI, Accuracy));
  764. }
  765. public bool IsPerpendicularTo(Vector vector)
  766. {
  767. return (ApproximatelyEqual(AngleTo(vector), Math.PI / 2));
  768. }
  769. /// <summary>
  770. /// Return rotated vector at transform data
  771. /// </summary>
  772. /// <param name="transform">transform matrix</param>
  773. /// <returns>rotated vector</returns>
  774. public Vector this[Transform transform]
  775. {
  776. get { return transform.TransformVector(this); }
  777. }
  778. #region INullable Members
  779. public bool IsNull { get { return m_null; } }//ApproximatelyEqual(x, 0) && ApproximatelyEqual(y, 0) && ApproximatelyEqual(z, 0);
  780. #endregion
  781. #region IEquatable<Vector> Members
  782. public override int GetHashCode()
  783. {
  784. return (int)Math.Sqrt(x * x * y * y * z * z);
  785. }
  786. public override bool Equals(object o)
  787. {
  788. if (o is Vector)
  789. {
  790. Vector v = (Vector)o;
  791. return !v.IsNull && Equals(v);
  792. }
  793. return false;
  794. }
  795. public bool Equals(Vector v)
  796. {
  797. return this == v;
  798. }
  799. public bool Equals(Vector vec, int tol)
  800. {
  801. return
  802. ApproximatelyEqual(vec.x, x, tol)
  803. &&
  804. ApproximatelyEqual(vec.y, y, tol)
  805. &&
  806. ApproximatelyEqual(vec.z, z, tol);
  807. }
  808. #endregion
  809. #region operators
  810. public static Vector operator +(Vector v1, Vector v2)
  811. {
  812. return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  813. }
  814. public static Vector operator -(Vector v1, Vector v2)
  815. {
  816. return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  817. }
  818. public static Vector operator *(Vector v1, double val)
  819. {
  820. return new Vector(v1.x * val, v1.y * val, v1.z * val);
  821. }
  822. public static Vector operator /(Vector v1, double val)
  823. {
  824. return new Vector(v1.x / val, v1.y / val, v1.z / val);
  825. }
  826. public static Vector operator ^(Vector v1, Vector v2)
  827. {
  828. #if L_ARM
  829. return new Vector(v2.y * v1.z - v2.z * v1.y, v2.z * v1.x - v2.x * v1.z, v2.x * v1.y - v2.y * v1.x);
  830. #else
  831. return new Vector(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x);
  832. #endif
  833. }
  834. public static double operator *(Vector v1, Vector v2)
  835. {
  836. return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  837. }
  838. public static bool operator ==(Vector v1, Vector v2)
  839. {
  840. return
  841. ApproximatelyEqual(v1.x, v2.x)
  842. &&
  843. ApproximatelyEqual(v1.y, v2.y)
  844. &&
  845. ApproximatelyEqual(v1.z, v2.z);
  846. }
  847. public static bool operator !=(Vector v1, Vector v2)
  848. {
  849. return !(v1 == v2);
  850. }
  851. public static implicit operator double[](Vector v1)
  852. {
  853. double[] arr = new double[3];
  854. arr[0] = v1.x;
  855. arr[1] = v1.y;
  856. arr[2] = v1.z;
  857. return arr;
  858. }
  859. public static implicit operator Vector(double[] points)
  860. {
  861. Vector v = new Vector();
  862. if (points != null && points.Length >= 2)
  863. {
  864. v.x = points[0];
  865. v.y = points[1];
  866. v.z = points[2];
  867. }
  868. else
  869. throw new ArgumentOutOfRangeException("Array size have to be equal or greater than 3 elements");
  870. return v;
  871. }
  872. #endregion
  873. #region static members
  874. public static Vector Null
  875. {
  876. get
  877. {
  878. Vector v = new Vector();
  879. v.m_null = true;
  880. return v;
  881. }
  882. }
  883. /// <summary>
  884. /// Calculate angle between vectors v1 and v2. All vectors mut be vectors with unit length
  885. /// </summary>
  886. /// <param name="axis">required to define sign of the angle</param>
  887. /// <param name="v1">first vector</param>
  888. /// <param name="v2">second vector</param>
  889. /// <returns>return signed angle value in radians</returns>
  890. public static double GetAngleZBetweenVectors(Vector axis, Vector v1, Vector v2)
  891. {
  892. Vector tmp = (v1 ^ v2);
  893. double cosAngle = v2 * v1;
  894. double angle = Math.Acos(cosAngle);
  895. if (Double.IsNaN(angle))
  896. angle = 0;
  897. if (tmp * axis < 0) //cos 90+ is negative
  898. angle = -angle;
  899. return angle;
  900. }
  901. #endregion
  902. }
  903. #endregion
  904. #region Point definition
  905. //[System.Diagnostics.DebuggerDisplay("{format(4)}", Name = "Point")]
  906. [Serializable]
  907. [DataContract]
  908. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  909. public struct Point : IEquatable<Point>, INullable, IBinarySerialize
  910. {
  911. [DataMember]
  912. public double x, y, z;
  913. private bool m_null;
  914. private string format(byte dig)
  915. {
  916. Point p = RoundTo(this, dig);
  917. return "(" + p.x.ToString() + "; " + p.y.ToString() + "; " + p.z.ToString() + ")";
  918. }
  919. public Point(double x, double y, double z)
  920. {
  921. m_null = false;
  922. this.x = x;
  923. this.y = y;
  924. this.z = z;
  925. }
  926. public Point(double x, double y) : this(x, y, 0) { }
  927. public void Translate(Vector vector)
  928. {
  929. x += vector.x;
  930. y += vector.y;
  931. z += vector.z;
  932. }
  933. public Point GetTranslated(Vector vector)
  934. {
  935. return this[vector];
  936. }
  937. public Point GetTransformed(Matrix3 matrix)
  938. {
  939. throw new NotImplementedException();
  940. }
  941. public void Transform(Matrix3 matrix)
  942. {
  943. throw new NotImplementedException();
  944. }
  945. public override int GetHashCode()
  946. {
  947. return base.GetHashCode();
  948. }
  949. public void Round(uint digits)
  950. {
  951. double factor1 = default(double);
  952. double factor2 = factor1;
  953. if (Factor(digits, out factor1, out factor2))
  954. {
  955. x = (int)x;
  956. y = (int)y;
  957. z = (int)z;
  958. }
  959. else
  960. {
  961. x = ((int)(x * factor2)) * factor1;
  962. y = ((int)(y * factor2)) * factor1;
  963. z = ((int)(z * factor2)) * factor1;
  964. }
  965. }
  966. public void MirrorAtOrigin()
  967. {
  968. x = -x;
  969. y = -y;
  970. z = -z;
  971. }
  972. public double DistanceTo(Point point)
  973. {
  974. return this[point].Length();
  975. }
  976. #region IEquatable<Point> Members
  977. public override bool Equals(object obj)
  978. {
  979. if (obj is Point)
  980. {
  981. var point = (Point)obj;
  982. if (this.x.Equals(point.x) && this.y.Equals(point.y) && this.z.Equals(point.z))
  983. return true;
  984. }
  985. return false;
  986. }
  987. public bool Equals(Point point)
  988. {
  989. return this == point;
  990. }
  991. #endregion
  992. public bool IsOrigin { get { return ApproximatelyEqual(x, 0) && ApproximatelyEqual(y, 0) && ApproximatelyEqual(z, 0); } }
  993. #region INullable Members
  994. public bool IsNull { get { return m_null; } }
  995. #endregion
  996. /// <summary>
  997. /// Returns non normailzed vector from this point and another
  998. /// </summary>
  999. /// <param name="end">Another point</param>
  1000. /// <returns></returns>
  1001. public Vector this[Point end]
  1002. {
  1003. get { return new Vector(end.x - x, end.y - y, end.z - z); }
  1004. }
  1005. /// <summary>
  1006. /// Returns point into new Transformation
  1007. /// </summary>
  1008. /// <param name="matrix">Transform matrix</param>
  1009. /// <returns></returns>
  1010. public Point this[Transform transform]
  1011. {
  1012. get
  1013. {
  1014. return transform.TransformPoint(this);
  1015. }
  1016. }
  1017. /// <summary>
  1018. /// Returns translated point at direction <paramref name="vactor"/>
  1019. /// </summary>
  1020. /// <param name="vector">translate direction</param>
  1021. /// <returns></returns>
  1022. public Point this[Vector vector] { get { return this + vector; } }
  1023. #region operators
  1024. public static bool operator ==(Point p1, object p2)
  1025. {
  1026. if (p2 == default(object))
  1027. return false;
  1028. return p1 == (Point)p2;
  1029. }
  1030. public static bool operator !=(Point p1, object p2)
  1031. {
  1032. if (p2 == default(object))
  1033. return true;
  1034. return p1 != (Point)p2;
  1035. }
  1036. public static bool operator ==(Point p1, Point p2)
  1037. {
  1038. return
  1039. Math.Abs(p1.x - p2.x) < Accuracy
  1040. &&
  1041. Math.Abs(p1.y - p2.y) < Accuracy
  1042. &&
  1043. Math.Abs(p1.z - p2.z) < Accuracy;
  1044. }
  1045. public static bool operator !=(Point p1, Point p2)
  1046. {
  1047. return !(p1 == p2);
  1048. }
  1049. public static Point operator +(Point point, Vector vector)
  1050. {
  1051. return new Point(point.x + vector.x, point.y + vector.y, point.z + vector.z);
  1052. }
  1053. public static Point operator -(Point point, Vector vector)
  1054. {
  1055. return new Point(point.x - vector.x, point.y - vector.y, point.z - vector.z);
  1056. }
  1057. public static Vector operator -(Point point1, Point point2)
  1058. {
  1059. return new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z);
  1060. }
  1061. public static Vector operator +(Point point1, Point point2)
  1062. {
  1063. return new Vector(point1.x + point2.x, point1.y + point2.y, point1.z + point2.z);
  1064. }
  1065. #endregion
  1066. #region static members
  1067. public static Point Null
  1068. {
  1069. get
  1070. {
  1071. Point p = new Point();
  1072. p.m_null = true;
  1073. return p;
  1074. }
  1075. }
  1076. #endregion
  1077. #region IBinarySerialize Members
  1078. public void Read(System.IO.BinaryReader r)
  1079. {
  1080. m_null = r.ReadBoolean();
  1081. x = r.ReadDouble();
  1082. y = r.ReadDouble();
  1083. z = r.ReadDouble();
  1084. }
  1085. public void Write(System.IO.BinaryWriter w)
  1086. {
  1087. w.Write(m_null);
  1088. w.Write(x);
  1089. w.Write(y);
  1090. w.Write(z);
  1091. }
  1092. #endregion
  1093. }
  1094. #endregion
  1095. #region Plane definition
  1096. //[System.Diagnostics.DebuggerDisplay("{format(4)}", Name = "Plane")]
  1097. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  1098. public struct Plane :INullable
  1099. {
  1100. private double[,] m_matr;
  1101. private bool m_null;
  1102. private string format(byte dig)
  1103. {
  1104. //Plane p = RoundTo(this, dig);
  1105. //"(" + p.x.ToString() + "; " + p.y.ToString() + "; " + p.z.ToString() + ")";
  1106. return string.Empty;
  1107. }
  1108. public Plane(Vector normal, Point point)
  1109. : this()
  1110. {
  1111. m_matr = new double[3, 3];
  1112. Vector perp1 = normal.GetPerpVector();
  1113. Vector perp2 = perp1 ^ normal;
  1114. Point p1 = point, p2 = point + perp1, p3 = point + perp2;
  1115. m_matr[0, 0] = p1.x;
  1116. m_matr[0, 1] = p1.y;
  1117. m_matr[0, 2] = p1.z;
  1118. m_matr[1, 0] = p2.x - p1.x;
  1119. m_matr[1, 1] = p2.y - p1.y;
  1120. m_matr[1, 2] = p2.z - p1.z;
  1121. m_matr[2, 0] = p3.x - p1.x;
  1122. m_matr[2, 1] = p3.y - p1.y;
  1123. m_matr[2, 2] = p3.z - p1.z;
  1124. }
  1125. public Plane(Point p1, Point p2, Point p3)
  1126. : this()
  1127. {
  1128. m_matr = new double[3, 3];
  1129. m_matr[0, 0] = p1.x;
  1130. m_matr[0, 1] = p1.y;
  1131. m_matr[0, 2] = p1.z;
  1132. m_matr[1, 0] = p2.x - p1.x;
  1133. m_matr[1, 1] = p2.y - p1.y;
  1134. m_matr[1, 2] = p2.z - p1.z;
  1135. m_matr[2, 0] = p3.x - p1.x;
  1136. m_matr[2, 1] = p3.y - p1.y;
  1137. m_matr[2, 2] = p3.z - p1.z;
  1138. }
  1139. public Plane(Vector v1, Vector v2, Point p): this()
  1140. {
  1141. m_matr = new double[3, 3];
  1142. Point p1 = p, p2 = p + v1, p3 = p + v2;
  1143. m_matr[0, 0] = p1.x;
  1144. m_matr[0, 1] = p1.y;
  1145. m_matr[0, 2] = p1.z;
  1146. m_matr[1, 0] = p2.x - p1.x;
  1147. m_matr[1, 1] = p2.y - p1.y;
  1148. m_matr[1, 2] = p2.z - p1.z;
  1149. m_matr[2, 0] = p3.x - p1.x;
  1150. m_matr[2, 1] = p3.y - p1.y;
  1151. m_matr[2, 2] = p3.z - p1.z;
  1152. }
  1153. public bool Contains(Vector vector)
  1154. {
  1155. return Contains(new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2])[vector]);
  1156. }
  1157. public bool Contains(Point point)
  1158. {
  1159. double a = point.x - m_matr[0, 0];
  1160. double b = point.y - m_matr[0, 1];
  1161. double c = point.z - m_matr[0, 2];
  1162. double det = a * m_matr[1, 1] * m_matr[2, 2];
  1163. det += b * m_matr[1, 2] * m_matr[2, 0];
  1164. det += c * m_matr[1, 0] * m_matr[2, 1];
  1165. det -= c * m_matr[1, 1] * m_matr[2, 0];
  1166. det -= b * m_matr[1, 0] * m_matr[2, 2];
  1167. det -= a * m_matr[1, 2] * m_matr[2, 1];
  1168. return ApproximatelyEqual(det, 0.0);
  1169. }
  1170. public double DistanceTo(Point point)
  1171. {
  1172. double[] x = new double[3];
  1173. double[] y = new double[3];
  1174. double[] z = new double[3];
  1175. for (int i = 0; i < 3; ++i)
  1176. {
  1177. x[i] = m_matr[i, 0];
  1178. y[i] = m_matr[i, 1];
  1179. z[i] = m_matr[i, 2];
  1180. }
  1181. double A = y[1] * z[2] - z[1] * y[2];
  1182. double B = x[2] * z[1] - x[1] * z[2];
  1183. double C = x[1] * y[2] - x[2] * y[1];
  1184. double D = x[0] * (z[1] * y[2] - y[1] * z[2]);
  1185. D += x[1] * (z[2] * y[0] - y[2] * z[0]);
  1186. D += x[2] * (y[1] * z[0] - z[1] * y[0]);
  1187. double retval = (A * point.x) + (B * point.y) + (C * point.z) + D;
  1188. retval /= Math.Sqrt((A * A) + (B * B) + (C * C));
  1189. return Math.Abs(retval);
  1190. }
  1191. public double DistanceTo(Plane plane)
  1192. {
  1193. return DistanceTo(new Point(plane.m_matr[0, 0], plane.m_matr[0, 1], m_matr[0, 2]));
  1194. }
  1195. public Point[] points
  1196. {
  1197. get
  1198. {
  1199. Point[] retval = new Point[3];
  1200. retval[0] = new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2]);
  1201. Vector vec = new Vector(m_matr[1, 0], m_matr[1, 1], m_matr[1, 2]);
  1202. retval[1] = retval[0] + vec;
  1203. vec = new Vector(m_matr[2, 0], m_matr[2, 1], m_matr[2, 2]);
  1204. retval[2] = retval[0] + vec;
  1205. return retval;
  1206. }
  1207. }
  1208. private Point intersect(Point a, Point b)
  1209. {
  1210. //sometimes (like in th bug #2307) we have very large inaccuracy
  1211. //so we need to square our angle to prevent the error
  1212. double angle = this.AngleTo(a[b]);
  1213. if (ApproximatelyEqual(Math.Pow(angle, 2), 0.0))
  1214. return Point.Null;
  1215. Point p = new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2]);
  1216. Vector l = new Vector(m_matr[1, 0], m_matr[1, 1], m_matr[1, 2]);
  1217. Vector m = new Vector(m_matr[2, 0], m_matr[2, 1], m_matr[2, 2]);
  1218. Vector val = l ^ m;
  1219. Point q = a + ((b - a) * (((p - a) * val) / ((b - a) * val)));
  1220. return q;
  1221. }
  1222. public Point[] Intersect(Plane plane)
  1223. {
  1224. Point[] ret = new Point[2];
  1225. Point[] pts = points;
  1226. List<Point[]> lines1 = new List<Point[]>();
  1227. lines1.Add(new Point[] { pts[0], pts[1]});
  1228. lines1.Add(new Point[] { pts[1], pts[2] });
  1229. lines1.Add(new Point[] { pts[2], pts[0] });
  1230. int k = 0;
  1231. for (int i = 0; i < lines1.Count; ++i)
  1232. if (!plane.IsParallel(lines1[i][1][lines1[i][0]]) && k != 2)
  1233. {
  1234. ret[k] = plane.intersect(lines1[i][0], lines1[i][1]);
  1235. k++;
  1236. }
  1237. if (k != 2)
  1238. return new Point[0];
  1239. return ret;
  1240. }
  1241. public Vector ParallelVector() { return (Normal ^ new Vector(0, 0, 1)).GetNormalized(); }
  1242. public Vector Normal
  1243. {
  1244. get
  1245. {
  1246. double[] x = new double[3];
  1247. double[] y = new double[3];
  1248. double[] z = new double[3];
  1249. for (int i = 0; i < 3; ++i)
  1250. {
  1251. x[i] = m_matr[i, 0];
  1252. y[i] = m_matr[i, 1];
  1253. z[i] = m_matr[i, 2];
  1254. }
  1255. double A = y[1] * z[2] - z[1] * y[2];
  1256. double B = x[2] * z[1] - x[1] * z[2];
  1257. double C = x[1] * y[2] - x[2] * y[1];
  1258. return (new Vector(A, B, C).GetNormalized());
  1259. }
  1260. }
  1261. public bool IsParallel(Plane p)
  1262. {
  1263. return Normal.IsParallelTo(p.Normal);
  1264. }
  1265. public bool IsParallel(Vector vector)
  1266. {
  1267. double angle = 0.0;
  1268. angle = Normal.AngleTo(vector);
  1269. return ApproximatelyEqual(angle, Math.PI) || ApproximatelyEqual(angle, 0) ;
  1270. }
  1271. public double AngleTo(Vector vector)
  1272. {
  1273. double angle = Normal.AngleTo(vector);
  1274. angle = (angle < (Math.PI / 2)) ? (Math.PI / 2 - angle) : angle - (Math.PI / 2);
  1275. return angle;
  1276. }
  1277. #region INullable Members
  1278. public bool IsNull { get { return m_null; } }
  1279. #endregion
  1280. #region Projection
  1281. public Point Projection(Point point)
  1282. {
  1283. double dist = DistanceTo(point);
  1284. Vector norm = Normal.GetNormalized();
  1285. Point pr = point - (norm * dist);
  1286. if (!ApproximatelyEqual(DistanceTo(pr), 0))
  1287. pr = point + (norm * dist);
  1288. return pr;
  1289. }
  1290. public Vector Projection(Vector vector)
  1291. {
  1292. Point p1 = new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2]);
  1293. Point p2 = Projection(p1[vector]);
  1294. return p1[p2];
  1295. }
  1296. #endregion
  1297. #region Shift
  1298. public void Shift(Vector direction)
  1299. {
  1300. Point
  1301. p1 = new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2]),
  1302. p2 = new Point(m_matr[1, 0] + p1.x, m_matr[1, 1] + p1.y, m_matr[1, 2] + p1.z),
  1303. p3 = new Point(m_matr[2, 0] + p1.x, m_matr[2, 1] + p1.y, m_matr[2, 2] + p1.z);
  1304. p1 = p1 + direction;
  1305. p2 = p2 + direction;
  1306. p3 = p3 + direction;
  1307. m_matr[0, 0] = p1.x;
  1308. m_matr[0, 1] = p1.y;
  1309. m_matr[0, 2] = p1.z;
  1310. m_matr[1, 0] = p2.x - p1.x;
  1311. m_matr[1, 1] = p2.y - p1.y;
  1312. m_matr[1, 2] = p2.z - p1.z;
  1313. m_matr[2, 0] = p3.x - p1.x;
  1314. m_matr[2, 1] = p3.y - p1.y;
  1315. m_matr[2, 2] = p3.z - p1.z;
  1316. }
  1317. public void Shift(double distance)
  1318. {
  1319. Shift(Normal * distance);
  1320. }
  1321. public Plane GetShifted(Vector direction)
  1322. {
  1323. Plane plane = this;
  1324. plane.Shift(direction);
  1325. return plane;
  1326. }
  1327. public Plane GetShifted(double distance)
  1328. {
  1329. Plane plane = this;
  1330. plane.Shift(distance);
  1331. return plane;
  1332. }
  1333. #endregion
  1334. public DecartPosition DetectDecartPart(Vector v)
  1335. {
  1336. if (
  1337. ApproximatelyEqual(v.x, 0)
  1338. & ApproximatelyEqual(v.y, 0)
  1339. & ApproximatelyEqual(v.z, 0))
  1340. return DecartPosition.Origin;
  1341. if (v.x > 0 & v.y > 0)
  1342. return DecartPosition.At1;
  1343. if (v.x > 0 & v.y < 0)
  1344. return DecartPosition.At2;
  1345. if (v.x < 0 & v.y < 0)
  1346. return DecartPosition.At3;
  1347. if (v.x < 0 & v.y > 0)
  1348. return DecartPosition.At4;
  1349. if (v.x > 0 & v.y == 0)
  1350. return DecartPosition.AtY_PlusX;
  1351. if (v.x < 0 & v.y == 0)
  1352. return DecartPosition.AtY_MinusX;
  1353. if (v.x == 0 & v.y > 0)
  1354. return DecartPosition.AtX_PlusY;
  1355. if (v.x == 0 & v.y < 0)
  1356. return DecartPosition.AtX_MinusY;
  1357. throw new InvalidOperationException();
  1358. }
  1359. public DecartPosition DetectDecartPart(Point p)
  1360. {
  1361. if (
  1362. ApproximatelyEqual(p.x, 0)
  1363. & ApproximatelyEqual(p.y, 0)
  1364. & ApproximatelyEqual(p.z, 0))
  1365. return DecartPosition.Origin;
  1366. if (p.x > 0 & p.y > 0)
  1367. return DecartPosition.At1;
  1368. if (p.x > 0 & p.y < 0)
  1369. return DecartPosition.At2;
  1370. if (p.x < 0 & p.y < 0)
  1371. return DecartPosition.At3;
  1372. if (p.x < 0 & p.y > 0)
  1373. return DecartPosition.At4;
  1374. if (p.x > 0 & p.y == 0)
  1375. return DecartPosition.AtY_PlusX;
  1376. if (p.x < 0 & p.y == 0)
  1377. return DecartPosition.AtY_MinusX;
  1378. if (p.x == 0 & p.y > 0)
  1379. return DecartPosition.AtX_PlusY;
  1380. if (p.x == 0 & p.y < 0)
  1381. return DecartPosition.AtX_MinusY;
  1382. throw new InvalidOperationException();
  1383. }
  1384. #region static members
  1385. public static Plane Null
  1386. {
  1387. get
  1388. {
  1389. Plane p = new Plane();
  1390. p.m_null = true;
  1391. return p;
  1392. }
  1393. }
  1394. #endregion
  1395. }
  1396. #endregion
  1397. #region Quaterion definition
  1398. //[System.Diagnostics.DebuggerDisplay("{format(8)}", Name = "Quaterion")]
  1399. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  1400. public struct Quaterion : INullable
  1401. {
  1402. private Vector vector;
  1403. private double w;
  1404. private bool m_null;
  1405. private string format(byte dig)
  1406. {
  1407. Quaterion q = RoundTo(this, dig);
  1408. return "(" + q.vector.x.ToString() + "; " + q.vector.y.ToString() + "; " + q.vector.z.ToString() + ";" + q.w.ToString() + "), Length:" + q.vector.Length().ToString();
  1409. }
  1410. public Quaterion(double x, double y, double z, double w)
  1411. : this()
  1412. {
  1413. vector = new Vector(x, y, z);
  1414. this.w = w;
  1415. }
  1416. public Quaterion(double x, double y, double z) : this(x, y, z, 0) { }
  1417. /// <summary>
  1418. ///
  1419. /// </summary>
  1420. /// <param name="axis">Rotation axis</param>
  1421. /// <param name="angle">In radians</param>
  1422. public Quaterion(Vector axis, double angle) : this(axis.x, axis.y, axis.z, angle) { }
  1423. /// <summary>
  1424. /// Length of the quaterion
  1425. /// </summary>
  1426. public double Norma
  1427. {
  1428. get { return vector.Length2() + w*w; }
  1429. }
  1430. public Vector Vector
  1431. {
  1432. get { return vector; }
  1433. set { vector = value; }
  1434. }
  1435. public double W
  1436. {
  1437. get { return w; }
  1438. set { w = value; }
  1439. }
  1440. public double Magnitude { get { return Math.Sqrt(Norma); } }
  1441. public Quaterion Conjugate
  1442. {
  1443. get
  1444. {
  1445. Quaterion q = this;
  1446. q.vector = vector.GetInverse();
  1447. return q;
  1448. }
  1449. }
  1450. public Quaterion Negate
  1451. {
  1452. get { return new Quaterion(-vector.x, -vector.y, -vector.z, -w); }
  1453. }
  1454. public double Angle { get { return Math.Acos(w) * 2.0; } }
  1455. public void FromAngleAxis(double Angle, Vector axis) // set the Quaternion by Angle-axis
  1456. {
  1457. double x = axis.x;
  1458. double y = axis.y;
  1459. double z = axis.z;
  1460. // required: Normalize the axis
  1461. double i_length = 1.0 / Math.Sqrt(x * x + y * y + z * z);
  1462. x = x * i_length;
  1463. y = y * i_length;
  1464. z = z * i_length;
  1465. // now make a clQuaternionernion out of it
  1466. double Half = DegToRad(Angle * 0.5);
  1467. w = Math.Cos(Half);//this used to be w/o deg to rad.
  1468. double sin_theta_over_two = Math.Sin(Half);
  1469. x = x * sin_theta_over_two;
  1470. y = y * sin_theta_over_two;
  1471. z = z * sin_theta_over_two;
  1472. vector = new Vector(x, y, z);
  1473. }
  1474. public void FromAngleAxis2(double AngleRadians, Vector axis)
  1475. {
  1476. double s;
  1477. s = Math.Sin(AngleRadians * 0.5f);
  1478. w = Math.Cos(AngleRadians * 0.5f);
  1479. vector.x = axis.x * s;
  1480. vector.y = axis.y * s;
  1481. vector.z = axis.z * s;
  1482. }
  1483. public void Normalize()
  1484. {
  1485. double mag = Norma;
  1486. if (mag> 0)
  1487. {
  1488. double factor = 1.0 / Math.Sqrt(mag);
  1489. vector.x *= factor;
  1490. vector.y *= factor;
  1491. vector.z *= factor;
  1492. w *= factor;
  1493. }
  1494. }
  1495. public void Slerp(double t, Quaterion left, Quaterion q2)
  1496. {
  1497. double quatEpsilon = 1.0e-8;
  1498. vector = left.vector;
  1499. w = left.w;
  1500. double cosine =
  1501. vector.x * q2.vector.x +
  1502. vector.y * q2.vector.y +
  1503. vector.z * q2.vector.z +
  1504. w * q2.w; //this is left.dot(right)
  1505. double sign = 1.0;
  1506. if (cosine < 0)
  1507. {
  1508. cosine = -cosine;
  1509. sign = -1.0;
  1510. }
  1511. double Sin = 1.0 - cosine * cosine;
  1512. if (Sin >= quatEpsilon * quatEpsilon)
  1513. {
  1514. Sin = Math.Sqrt(Sin);
  1515. double _angle = Math.Atan2(Sin, cosine);
  1516. double i_sin_angle = 1.0 / Sin;
  1517. double lower_weight = Math.Sin(_angle * (1.0 - t)) * i_sin_angle;
  1518. double upper_weight = Math.Sin(_angle * t) * i_sin_angle * sign;
  1519. w = (w * (lower_weight)) + (q2.w * (upper_weight));
  1520. vector.x = (vector.x * (lower_weight)) + (q2.vector.x * (upper_weight));
  1521. vector.y = (vector.y * (lower_weight)) + (q2.vector.y * (upper_weight));
  1522. vector.z = (vector.z * (lower_weight)) + (q2.vector.z * (upper_weight));
  1523. }
  1524. }
  1525. /// <summary>
  1526. /// returns axis and angle of rotation of quaternion
  1527. /// </summary>
  1528. /// <param name="angle"></param>
  1529. /// <param name="axis"></param>
  1530. public void GetAngleAxis(out double angle, ref Vector axis)
  1531. {
  1532. angle = Math.Acos(w) * 2.0;
  1533. angle = RadToDeg(angle);
  1534. double sa = Math.Sqrt(1.0 - w * w);
  1535. if (sa != 0)
  1536. {
  1537. sa = 1 / sa;
  1538. axis.x = vector.x * sa;
  1539. axis.y = vector.y * sa;
  1540. axis.z = vector.z * sa;
  1541. }
  1542. else
  1543. {
  1544. axis.x = 1.0;
  1545. axis.y = 0.0;
  1546. axis.z = 0.0;
  1547. }
  1548. }
  1549. public void Round(uint digits)
  1550. {
  1551. double factor1 = default(double);
  1552. double factor2 = factor1;
  1553. if (Factor(digits, out factor1, out factor2))
  1554. {
  1555. vector.x = (int)vector.x;
  1556. vector.y = (int)vector.y;
  1557. vector.z = (int)vector.z;
  1558. w = (int)w;
  1559. }
  1560. else
  1561. {
  1562. vector.x = ((int)(vector.x * factor2)) * factor1;
  1563. vector.y = ((int)(vector.y * factor2)) * factor1;
  1564. vector.z = ((int)(vector.z * factor2)) * factor1;
  1565. w = ((int)(w* factor2)) * factor1;
  1566. }
  1567. }
  1568. public Vector Rotate(Vector v)
  1569. {
  1570. Vector qv = vector;
  1571. return (v * (w * w - 0.5) + (qv ^ v) * w + qv * (qv * v)) * 2;
  1572. }
  1573. public Vector InvRotate(Vector v)
  1574. {
  1575. Vector qv = vector;
  1576. return (v * (w * w - 0.5) - (qv ^ v) * w + qv * (qv * v)) * 2;
  1577. }
  1578. public Vector Transform(Vector vec, Vector position)
  1579. {
  1580. return Rotate(vec) + position;
  1581. }
  1582. public Vector InvTransform(Vector vec, Vector position)
  1583. {
  1584. return InvRotate(vec - position);
  1585. }
  1586. //public void Multiply(
  1587. #region static members
  1588. public static Quaterion operator +(Quaterion q1, Quaterion q2)
  1589. {
  1590. return new Quaterion(q1.vector.x + q2.vector.x, q1.vector.y + q2.vector.y, q1.vector.z + q2.vector.z, q1.w + q2.w);
  1591. }
  1592. public static Quaterion operator -(Quaterion q1, Quaterion q2)
  1593. {
  1594. return new Quaterion(q1.vector.x - q2.vector.x, q1.vector.y - q2.vector.y, q1.vector.z - q2.vector.z, q1.w - q2.w);
  1595. }
  1596. public static Quaterion operator ^(Quaterion q1, Quaterion q2)
  1597. {
  1598. double a, b, c, d;
  1599. a = q1.w * q2.w - q1.vector.x * q2.vector.x - q1.vector.y * q2.vector.y - q1.vector.z * q2.vector.z;
  1600. b = q1.w * q2.vector.x + q2.w * q1.vector.x + q1.vector.y * q2.vector.z - q2.vector.y * q1.vector.z;
  1601. c = q1.w * q2.vector.y + q2.w * q1.vector.y + q1.vector.z * q2.vector.x - q2.vector.z * q1.vector.x;
  1602. d = q1.w * q2.vector.z + q2.w * q1.vector.z + q1.vector.x * q2.vector.y - q2.vector.x * q1.vector.y;
  1603. return new Quaterion(b, c, d, a);
  1604. }
  1605. public static Quaterion operator ^(Quaterion q1, Vector q2)
  1606. {
  1607. double a, b, c, d;
  1608. a = -q1.vector.x * q2.x - q1.vector.y * q2.y - q1.vector.z * q2.z;
  1609. b = q1.w * q2.x + q1.vector.y * q2.z - q2.y * q1.vector.z;
  1610. c = q1.w * q2.y + q1.vector.z * q2.x - q2.z * q1.vector.x;
  1611. d = q1.w * q2.z + q1.vector.x * q2.y - q2.x * q1.vector.y;
  1612. return new Quaterion(b, c, d, a);
  1613. }
  1614. public static double operator *(Quaterion q1, Quaterion q2)
  1615. {
  1616. return q1.vector.x * q2.vector.x + q1.vector.y * q2.vector.y + q1.vector.z * q2.vector.z + q1.w * q2.w;
  1617. }
  1618. public static Quaterion Null
  1619. {
  1620. get
  1621. {
  1622. Quaterion q = new Quaterion();
  1623. q.m_null = true;
  1624. return q;
  1625. }
  1626. }
  1627. public static Quaterion Identity { get { return new Quaterion(0, 0, 0, 1); } }
  1628. #endregion
  1629. #region INullable Members
  1630. public bool IsNull
  1631. {
  1632. get { return m_null || vector.IsNull; }
  1633. }
  1634. #endregion
  1635. }
  1636. #endregion
  1637. #region Matrix definition
  1638. // [System.Diagnostics.DebuggerDisplay("{format(8)}", Name = "Matrix3")]
  1639. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  1640. public struct Matrix3: INullable, IEquatable<Matrix3>
  1641. {
  1642. private double[,] m_matrix;
  1643. private bool m_null;
  1644. private string format(byte dig)
  1645. {
  1646. return string.Empty;
  1647. }
  1648. public Matrix3(double[,] data)
  1649. {
  1650. m_null = false;
  1651. m_matrix = new double[3, 3]
  1652. {
  1653. {data[0,0], data[0,1], data[0,2]},
  1654. {data[1,0], data[1,1], data[1,2]},
  1655. {data[2,0], data[2,1], data[2,2]}
  1656. };
  1657. }
  1658. public Matrix3(double[] data)
  1659. {
  1660. m_null = false;
  1661. m_matrix = new double[3, 3]
  1662. {
  1663. {data[0], data[1], data[2]},
  1664. {data[3], data[4], data[5]},
  1665. {data[6], data[7], data[8]}
  1666. };
  1667. }
  1668. public Matrix3(Matrix3 matrix) : this(matrix.m_matrix) { }
  1669. public Matrix3(Quaterion q):this()
  1670. {
  1671. m_matrix = new double[3,3];
  1672. double w = q.W;
  1673. double x = q.Vector.x;
  1674. double y = q.Vector.y;
  1675. double z = q.Vector.z;
  1676. m_matrix[0,0] = 1.0 - y * y * 2.0 - z * z * 2.0;
  1677. m_matrix[0, 1] = x * y * 2.0 - w * z * 2.0;
  1678. m_matrix[0, 2] = x * z * 2.0 + w * y * 2.0;
  1679. m_matrix[1, 0] = x * y * 2.0 + w * z * 2.0;
  1680. m_matrix[1, 1] = 1.0 - x * x * 2.0 - z * z * 2.0;
  1681. m_matrix[1, 2] = y * z * 2.0 - w * x * 2.0;
  1682. m_matrix[2, 0] = x * z * 2.0 - w * y * 2.0;
  1683. m_matrix[2, 1] = y * z * 2.0 + w * x * 2.0;
  1684. m_matrix[2, 2] = 1.0 - x * x * 2.0 - y * y * 2.0;
  1685. }
  1686. /// <summary>
  1687. /// Creates matrix from Euler angles
  1688. /// </summary>
  1689. /// <param name="X"></param>
  1690. /// <param name="Y"></param>
  1691. /// <param name="Z"></param>
  1692. public Matrix3(double X, double Y, double Z): this()
  1693. {
  1694. m_matrix = new double[3, 3];
  1695. X = DegToRad(X);
  1696. Y = DegToRad(Y);
  1697. Z = DegToRad(Z);
  1698. Matrix3 RotZ = new Matrix3(
  1699. new Vector(Math.Cos(Z), -Math.Sin(Z), 0),
  1700. new Vector(Math.Sin(Z), Math.Cos(Z), 0),
  1701. new Vector(0, 0, 1));
  1702. Matrix3 RotY = new Matrix3(
  1703. new Vector(Math.Cos(Y), 0, Math.Sin(Y)),
  1704. new Vector(0, 1, 0),
  1705. new Vector(-Math.Sin(Y), 0, Math.Cos(Y)));
  1706. Matrix3 RotX = new Matrix3(
  1707. new Vector(1, 0, 0),
  1708. new Vector(0, Math.Cos(X), -Math.Sin(X)),
  1709. new Vector(0, Math.Sin(X), Math.Cos(X)));
  1710. m_matrix = (RotX * RotY * RotZ).m_matrix;
  1711. }
  1712. /// <summary>
  1713. /// Creates matrix from rotation an axis
  1714. /// </summary>
  1715. /// <param name="XX">Rotation at X-Axis</param>
  1716. /// <param name="YY">Rotation at Y-Axis</param>
  1717. /// <param name="ZZ">Rotation at Z-Axis</param>
  1718. public Matrix3(Vector XX, Vector YY, Vector ZZ): this()
  1719. {
  1720. m_matrix = new double[3, 3];
  1721. m_matrix[0, 0] = XX.x;
  1722. m_matrix[0, 1] = XX.y;
  1723. m_matrix[0, 2] = XX.z;
  1724. m_matrix[1, 0] = YY.x;
  1725. m_matrix[1, 1] = YY.y;
  1726. m_matrix[1, 2] = YY.z;
  1727. m_matrix[2, 0] = ZZ.x;
  1728. m_matrix[2, 1] = ZZ.y;
  1729. m_matrix[2, 2] = ZZ.z;
  1730. }
  1731. public Vector Column_get(int column)
  1732. {
  1733. return new Vector(
  1734. m_matrix[0, column]
  1735. ,m_matrix[1, column]
  1736. ,m_matrix[2, column]
  1737. );
  1738. }
  1739. public void Column_set(int column, Vector value)
  1740. {
  1741. m_matrix[0, column] = value.x;
  1742. m_matrix[1, column] = value.y;
  1743. m_matrix[2, column] = value.z;
  1744. }
  1745. public Vector Row_get(int row)
  1746. {
  1747. return new Vector(
  1748. m_matrix[row, 0]
  1749. ,m_matrix[row, 1]
  1750. ,m_matrix[row, 2]);
  1751. }
  1752. public void Row_set(int row, Vector value)
  1753. {
  1754. m_matrix[row, 0] = value.x;
  1755. m_matrix[row, 1] = value.y;
  1756. m_matrix[row, 2] = value.z;
  1757. }
  1758. public double[] RowMajor_get()
  1759. {
  1760. double[] ret = new double[9];
  1761. ret[0] = m_matrix[0, 0];
  1762. ret[1] = m_matrix[0, 1];
  1763. ret[2] = m_matrix[0, 2];
  1764. ret[3] = m_matrix[1, 0];
  1765. ret[4] = m_matrix[1, 1];
  1766. ret[5] = m_matrix[1, 2];
  1767. ret[6] = m_matrix[2, 0];
  1768. ret[7] = m_matrix[2, 1];
  1769. ret[8] = m_matrix[2, 2];
  1770. return ret;
  1771. }
  1772. public void RowMajor_set(double[] ret)
  1773. {
  1774. m_matrix[0, 0] = ret[0];
  1775. m_matrix[0, 1] = ret[1];
  1776. m_matrix[0, 2] = ret[2];
  1777. m_matrix[1, 0] = ret[3];
  1778. m_matrix[1, 1] = ret[4];
  1779. m_matrix[1, 2] = ret[5];
  1780. m_matrix[2, 0] = ret[6];
  1781. m_matrix[2, 1] = ret[7];
  1782. m_matrix[2, 2] = ret[8];
  1783. }
  1784. public double[] ColumnMajor_get()
  1785. {
  1786. double[] ret = new double[9];
  1787. ret[0] = m_matrix[0, 0];
  1788. ret[1] = m_matrix[1, 0];
  1789. ret[2] = m_matrix[2, 0];
  1790. ret[3] = m_matrix[0, 1];
  1791. ret[4] = m_matrix[1, 1];
  1792. ret[5] = m_matrix[2, 1];
  1793. ret[6] = m_matrix[0, 2];
  1794. ret[7] = m_matrix[1, 2];
  1795. ret[8] = m_matrix[2, 2];
  1796. return ret;
  1797. }
  1798. public void ColumnMajor_set(double[] ret)
  1799. {
  1800. m_matrix[0, 0] = ret[0];
  1801. m_matrix[1, 0] = ret[1];
  1802. m_matrix[2, 0] = ret[2];
  1803. m_matrix[0, 1] = ret[3];
  1804. m_matrix[1, 1] = ret[4];
  1805. m_matrix[2, 1] = ret[5];
  1806. m_matrix[0, 2] = ret[6];
  1807. m_matrix[1, 2] = ret[7];
  1808. m_matrix[2, 2] = ret[8];
  1809. }
  1810. public double[] Diag_Main
  1811. {
  1812. get
  1813. {
  1814. return new double[] { m_matrix[0, 0], m_matrix[1, 1], m_matrix[2, 2] };
  1815. }
  1816. }
  1817. public double this[int row, int column]
  1818. {
  1819. get { return m_matrix[row, column]; }
  1820. set { m_matrix[row, column] = value; }
  1821. }
  1822. /// <summary>
  1823. /// Data of the matrix
  1824. /// </summary>
  1825. public double[] Data{
  1826. get
  1827. {
  1828. return new double[] {
  1829. m_matrix[0, 0], m_matrix[0, 1], m_matrix[0, 2]
  1830. ,m_matrix[1, 0], m_matrix[1, 1], m_matrix[1, 2]
  1831. ,m_matrix[2, 0], m_matrix[2, 1], m_matrix[2, 2]
  1832. };
  1833. }
  1834. set{
  1835. m_matrix[0, 0] = value[0]; m_matrix[0, 1] = value[1]; m_matrix[0, 2] = value[2];
  1836. m_matrix[1, 0] = value[3]; m_matrix[1, 1] = value[4]; m_matrix[1, 2] = value[5];
  1837. m_matrix[2, 0] = value[6]; m_matrix[2, 1] = value[7]; m_matrix[2, 2] = value[8];
  1838. }
  1839. }
  1840. /// <summary>
  1841. /// Returns the Determinant of this matrix
  1842. /// </summary>
  1843. public double Determinant
  1844. {
  1845. get
  1846. {
  1847. return m_matrix[0, 0] * m_matrix[1, 1] * m_matrix[2, 2] + m_matrix[0, 1] * m_matrix[1, 2] * m_matrix[2, 0] + m_matrix[0, 2] * m_matrix[1, 0] * m_matrix[2, 1]
  1848. - m_matrix[0, 2] * m_matrix[1, 1] * m_matrix[2, 0] - m_matrix[0, 1] * m_matrix[1, 0] * m_matrix[2, 2] - m_matrix[0, 0] * m_matrix[1, 2] * m_matrix[2, 1];
  1849. }
  1850. }
  1851. /// <summary>
  1852. /// Transorm this matrix to quaterion
  1853. /// </summary>
  1854. public Quaterion Quaterion
  1855. {
  1856. get
  1857. {
  1858. Quaterion q = new Quaterion();
  1859. double tr, s;
  1860. double x, y, z;
  1861. tr = m_matrix[0, 0] + m_matrix[1, 1] + m_matrix[2, 2];
  1862. if (tr >= 0)
  1863. {
  1864. s = Math.Sqrt(tr + 1);
  1865. q.W = 0.5 * s;
  1866. s = 0.5 / s;
  1867. x = (this[2, 1] - this[1, 2]) * s;
  1868. y = (this[0, 2] - this[2, 0]) * s;
  1869. z = (this[1, 0] - this[0, 1]) * s;
  1870. q.Vector = new Vector(x, y, z);
  1871. }
  1872. else
  1873. {
  1874. int i = 0;
  1875. if (m_matrix[1, 1] > m_matrix[0, 0])
  1876. i = 1;
  1877. if (m_matrix[2, 2] > m_matrix[i, i])
  1878. i = 2;
  1879. switch (i)
  1880. {
  1881. case 0:
  1882. {
  1883. s = Math.Sqrt((m_matrix[0, 0] - (m_matrix[1, 1] + m_matrix[2, 2])) + 1);
  1884. x = 0.5 * s;
  1885. s = 0.5 / s;
  1886. y = (m_matrix[0, 1] + m_matrix[1, 0]) * s;
  1887. z = (m_matrix[2, 0] + m_matrix[0, 2]) * s;
  1888. q.W = (m_matrix[2, 1] - m_matrix[1, 2]) * s;
  1889. q.Vector = new Vector(x, y, z);
  1890. break;
  1891. }
  1892. case 1:
  1893. {
  1894. s = Math.Sqrt((m_matrix[1, 1] - (m_matrix[2, 2] + m_matrix[0, 0])) + 1);
  1895. y = 0.5 * s;
  1896. s = 0.5 / s;
  1897. z = (this[1, 2] + this[2, 1]) * s;
  1898. x = (this[0, 1] + this[1, 0]) * s;
  1899. q.W = (this[0, 2] - this[2, 0]) * s;
  1900. break;
  1901. }
  1902. case 2:
  1903. {
  1904. s = Math.Sqrt((m_matrix[2, 2] - (m_matrix[0, 0] + m_matrix[1, 1])) + 1);
  1905. z = 0.5 * s;
  1906. s = 0.5 / s;
  1907. x = (this[2, 0] + this[0, 2]) * s;
  1908. y = (this[1, 2] + this[2, 1]) * s;
  1909. q.W = (this[1, 0] - this[0, 1]) * s;
  1910. break;
  1911. }
  1912. }
  1913. }
  1914. return q;
  1915. }
  1916. }
  1917. /// <summary>
  1918. /// Get opposite matrix of this matrix
  1919. /// </summary>
  1920. public Matrix3 Inverse
  1921. {
  1922. get
  1923. {
  1924. double d = Determinant;
  1925. if (ApproximatelyEqual(d, 0.0))
  1926. {
  1927. return Null;
  1928. }
  1929. d = 1.0 / d;
  1930. double AlgExt11, AlgExt12, AlgExt13, AlgExt21, AlgExt22, AlgExt23, AlgExt31, AlgExt32, AlgExt33;
  1931. AlgExt11 = m_matrix[1, 1] * m_matrix[2, 2] - m_matrix[1, 2] * m_matrix[2, 1];
  1932. AlgExt21 = m_matrix[0, 2] * m_matrix[2, 1] - m_matrix[0, 1] * m_matrix[2, 2];
  1933. AlgExt31 = m_matrix[0, 1] * m_matrix[1, 2] - m_matrix[0, 2] * m_matrix[1, 1];
  1934. AlgExt12 = m_matrix[1, 2] * m_matrix[2, 0] - m_matrix[1, 0] * m_matrix[2, 2];
  1935. AlgExt22 = m_matrix[0, 0] * m_matrix[2, 2] - m_matrix[0, 2] * m_matrix[2, 0];
  1936. AlgExt32 = m_matrix[0, 2] * m_matrix[1, 0] - m_matrix[0, 0] * m_matrix[1, 2];
  1937. AlgExt13 = m_matrix[1, 0] * m_matrix[2, 1] - m_matrix[1, 1] * m_matrix[2, 0];
  1938. AlgExt23 = m_matrix[0, 1] * m_matrix[2, 0] - m_matrix[0, 0] * m_matrix[2, 1];
  1939. AlgExt33 = m_matrix[0, 0] * m_matrix[1, 1] - m_matrix[0, 1] * m_matrix[1, 0];
  1940. Matrix3 dest = new Matrix3();
  1941. dest.m_matrix = new double[,]{
  1942. {AlgExt11 * d, AlgExt21 * d, AlgExt31 * d},
  1943. {AlgExt12 * d, AlgExt22 * d, AlgExt32 * d},
  1944. {AlgExt13 * d, AlgExt23 * d, AlgExt33 * d},
  1945. };
  1946. ////Matrix3 dest = new Matrix3(new double[] {
  1947. //// AlgExt11 * d, AlgExt21 * d, AlgExt31 * d,
  1948. //// AlgExt12 * d, AlgExt22 * d, AlgExt32 * d,
  1949. //// AlgExt13 * d, AlgExt23 * d, AlgExt33 * d
  1950. ////});
  1951. return dest;
  1952. }
  1953. }
  1954. /// <summary>
  1955. /// true if this matrix is identity
  1956. /// </summary>
  1957. public bool IsIdentity
  1958. {
  1959. get
  1960. {
  1961. for (int i = 0; i < 3; i++)
  1962. for (int j = 0; j < 3; j++)
  1963. if (i != j)
  1964. { if (!ApproximatelyEqual(m_matrix[i, j], 0)) return false; }
  1965. else
  1966. { if (!ApproximatelyEqual(m_matrix[i, j], 1)) return false; }
  1967. return true;
  1968. }
  1969. }
  1970. /// <summary>
  1971. /// True if this matrix is nullable
  1972. /// </summary>
  1973. public bool IsZero
  1974. {
  1975. get
  1976. {
  1977. for (int i = 0; i < 3; i++)
  1978. for (int j = 0; j < 3; j++)
  1979. if (!ApproximatelyEqual(m_matrix[i, j], 0)) return false;
  1980. return true;
  1981. }
  1982. }
  1983. public Vector XAxis { get { return new Vector(m_matrix[0, 0], m_matrix[0, 1], m_matrix[0, 2]); } }
  1984. public Vector YAxis { get { return new Vector(m_matrix[1, 0], m_matrix[1, 1], m_matrix[1, 2]); } }
  1985. public Vector ZAxis { get { return new Vector(m_matrix[2, 0], m_matrix[2, 1], m_matrix[2, 2]); } }
  1986. /// <summary>
  1987. /// Makes this matrix as nullable
  1988. /// </summary>
  1989. public void Zero()
  1990. {
  1991. for (int i = 0; i < 3; i++)
  1992. for (int j = 0; j < 3; j++)
  1993. m_matrix[i, j] = 0;
  1994. }
  1995. /// <summary>
  1996. /// Negate this matrix
  1997. /// </summary>
  1998. public void Negate()
  1999. {
  2000. for (int i = 0; i < 3; i++)
  2001. for (int j = 0; j < 3; j++)
  2002. m_matrix[i, j] *= -1;
  2003. }
  2004. /// <summary>
  2005. /// Rotates current matrix at X axis
  2006. /// </summary>
  2007. /// <param name="angle">Angle in radians</param>
  2008. public void RotateXAxis(double angle)
  2009. {
  2010. Matrix3 RotX = new Matrix3(
  2011. new Vector(1, 0, 0),
  2012. new Vector(0, Math.Cos(angle), -Math.Sin(angle)),
  2013. new Vector(0, Math.Sin(angle), Math.Cos(angle)));
  2014. m_matrix = (this * RotX).m_matrix;
  2015. }
  2016. /// <summary>
  2017. /// Rotates current matrix at Y axis
  2018. /// </summary>
  2019. /// <param name="angle">Angle in radians</param>
  2020. public void RotateYAxis(double angle)
  2021. {
  2022. Matrix3 RotY = new Matrix3(
  2023. new Vector(Math.Cos(angle), 0, Math.Sin(angle)),
  2024. new Vector(0, 1, 0),
  2025. new Vector(-Math.Sin(angle), 0, Math.Cos(angle)));
  2026. m_matrix = (this * RotY).m_matrix;
  2027. }
  2028. /// <summary>
  2029. /// Rotates current matrix at Z axis
  2030. /// </summary>
  2031. /// <param name="angle">Angle in radians</param>
  2032. public void RotateZAxis(double angle)
  2033. {
  2034. Matrix3 RotZ = new Matrix3(
  2035. new Vector(Math.Cos(angle), -Math.Sin(angle), 0),
  2036. new Vector(Math.Sin(angle), Math.Cos(angle), 0),
  2037. new Vector(0, 0, 1));
  2038. this.Multiply(RotZ);
  2039. //m_matrix = (this * RotZ).m_matrix;
  2040. }
  2041. /// <summary>
  2042. /// Transpose this matrix
  2043. /// </summary>
  2044. public void Transpose()
  2045. {
  2046. for (int i = 0; i < 3; i++)
  2047. {
  2048. for (int j = 0; j < 3; j++)
  2049. {
  2050. double temp = m_matrix[i, j];
  2051. m_matrix[i, j] = m_matrix[j, i];
  2052. m_matrix[j, i] = temp;
  2053. }
  2054. }
  2055. }
  2056. /// <summary>
  2057. /// Returns rotated vector by this matrix
  2058. /// </summary>
  2059. /// <param name="vec">vector</param>
  2060. /// <returns></returns>
  2061. public Vector Multiply(Vector vec)
  2062. {
  2063. double x, y, z;
  2064. x = m_matrix[0, 0] * vec.x + m_matrix[1, 0] * vec.y + m_matrix[2, 0] * vec.z;
  2065. y = m_matrix[0, 1] * vec.x + m_matrix[1, 1] * vec.y + m_matrix[2, 1] * vec.z;
  2066. z = m_matrix[0, 2] * vec.x + m_matrix[1, 2] * vec.y + m_matrix[2, 2] * vec.z;
  2067. return new Vector(x, y, z);
  2068. }
  2069. /// <summary>
  2070. /// Returns rotated point by this matrix
  2071. /// </summary>
  2072. /// <param name="vec">point</param>
  2073. /// <returns></returns>
  2074. public Point Multiply(Point vec)
  2075. {
  2076. double x, y, z;
  2077. x = m_matrix[0, 0] * vec.x + m_matrix[1, 0] * vec.y + m_matrix[2, 0] * vec.z;
  2078. y = m_matrix[0, 1] * vec.x + m_matrix[1, 1] * vec.y + m_matrix[2, 1] * vec.z;
  2079. z = m_matrix[0, 2] * vec.x + m_matrix[1, 2] * vec.y + m_matrix[2, 2] * vec.z;
  2080. return new Point(x, y, z);
  2081. }
  2082. /// <summary>
  2083. /// Returns rotated vector by this matrix (transposed)
  2084. /// </summary>
  2085. /// <param name="vec">vector</param>
  2086. /// <returns></returns>
  2087. public Vector MultiplyByTranspose(Vector vec)
  2088. {
  2089. double x, y, z;
  2090. x = m_matrix[0, 0] * vec.x + m_matrix[0, 1] * vec.y + m_matrix[0, 2] * vec.z;
  2091. y = m_matrix[1, 0] * vec.x + m_matrix[1, 1] * vec.y + m_matrix[1, 2] * vec.z;
  2092. z = m_matrix[2, 0] * vec.x + m_matrix[2, 1] * vec.y + m_matrix[2, 2] * vec.z;
  2093. return new Vector(x, y, z);
  2094. }
  2095. /// <summary>
  2096. /// Adds matrix to current
  2097. /// </summary>
  2098. /// <param name="matrix"></param>
  2099. public void Add(Matrix3 matrix)
  2100. {
  2101. for (int i = 0; i < 3; i++)
  2102. for (int j = 0; j < 3; j++)
  2103. {
  2104. m_matrix[i, j] += matrix.m_matrix[i, j];
  2105. }
  2106. }
  2107. /// <summary>
  2108. /// Substract matrix from current
  2109. /// </summary>
  2110. /// <param name="matrix"></param>
  2111. public void Substract(Matrix3 matrix)
  2112. {
  2113. for (int i = 0; i < 3; i++)
  2114. for (int j = 0; j < 3; j++)
  2115. {
  2116. m_matrix[i, j] -= matrix.m_matrix[i, j];
  2117. }
  2118. }
  2119. /// <summary>
  2120. /// Multiplies matrix do double value
  2121. /// </summary>
  2122. /// <param name="value"></param>
  2123. public void Multiply(double value)
  2124. {
  2125. for (int i = 0; i < 3; i++)
  2126. for (int j = 0; j < 3; j++)
  2127. {
  2128. m_matrix[i, j] *= value;
  2129. }
  2130. }
  2131. /// <summary>
  2132. /// Multiply matrix to current
  2133. /// </summary>
  2134. /// <param name="matrix"></param>
  2135. public void Multiply(Matrix3 matrix)
  2136. {
  2137. double a, b, c, d, e, f, g, h, i;
  2138. //note: temps needed so that x.multiply(x,y) works OK.
  2139. a = m_matrix[0, 0] * matrix.m_matrix[0, 0] + m_matrix[0, 1] * matrix.m_matrix[1, 0] + m_matrix[0, 2] * matrix.m_matrix[2, 0];
  2140. b = m_matrix[0, 0] * matrix.m_matrix[0, 1] + m_matrix[0, 1] * matrix.m_matrix[1, 1] + m_matrix[0, 2] * matrix.m_matrix[2, 1];
  2141. c = m_matrix[0, 0] * matrix.m_matrix[0, 2] + m_matrix[0, 1] * matrix.m_matrix[1, 2] + m_matrix[0, 2] * matrix.m_matrix[2, 2];
  2142. d = m_matrix[1, 0] * matrix.m_matrix[0, 0] + m_matrix[1, 1] * matrix.m_matrix[1, 0] + m_matrix[1, 2] * matrix.m_matrix[2, 0];
  2143. e = m_matrix[1, 0] * matrix.m_matrix[0, 1] + m_matrix[1, 1] * matrix.m_matrix[1, 1] + m_matrix[1, 2] * matrix.m_matrix[2, 1];
  2144. f = m_matrix[1, 0] * matrix.m_matrix[0, 2] + m_matrix[1, 1] * matrix.m_matrix[1, 2] + m_matrix[1, 2] * matrix.m_matrix[2, 2];
  2145. g = m_matrix[2, 0] * matrix.m_matrix[0, 0] + m_matrix[2, 1] * matrix.m_matrix[1, 0] + m_matrix[2, 2] * matrix.m_matrix[2, 0];
  2146. h = m_matrix[2, 0] * matrix.m_matrix[0, 1] + m_matrix[2, 1] * matrix.m_matrix[1, 1] + m_matrix[2, 2] * matrix.m_matrix[2, 1];
  2147. i = m_matrix[2, 0] * matrix.m_matrix[0, 2] + m_matrix[2, 1] * matrix.m_matrix[1, 2] + m_matrix[2, 2] * matrix.m_matrix[2, 2];
  2148. // fill data
  2149. m_matrix[0, 0] = a;
  2150. m_matrix[0, 1] = b;
  2151. m_matrix[0, 2] = c;
  2152. m_matrix[1, 0] = d;
  2153. m_matrix[1, 1] = e;
  2154. m_matrix[1, 2] = f;
  2155. m_matrix[2, 0] = g;
  2156. m_matrix[2, 1] = h;
  2157. m_matrix[2, 2] = i;
  2158. }
  2159. public void Round(uint digits)
  2160. {
  2161. double factor1 = default(double);
  2162. double factor2 = factor1;
  2163. if (Factor(digits, out factor1, out factor2))
  2164. {
  2165. for (int i = 0; i < 3; i++)
  2166. {
  2167. for (int j = 0; j < 3; j++)
  2168. {
  2169. m_matrix[i, j] = (int)m_matrix[i, j];
  2170. }
  2171. }
  2172. }
  2173. else
  2174. {
  2175. for (int i = 0; i < 3; i++)
  2176. {
  2177. for (int j = 0; j < 3; j++)
  2178. {
  2179. m_matrix[i, j] = ((int)(m_matrix[i, j] * factor2)) * factor1;
  2180. }
  2181. }
  2182. }
  2183. }
  2184. #region operators
  2185. public static bool operator ==(Matrix3 m1, Matrix3 m2)
  2186. {
  2187. if (m1 == default(Matrix3) | m1 == default(Matrix3))
  2188. {
  2189. return false;
  2190. }
  2191. if (m1.m_null | m2.m_null)
  2192. return false;
  2193. if (System.Object.ReferenceEquals(m1, m2))
  2194. {
  2195. return true;
  2196. }
  2197. for (int i = 0; i < 3; i++)
  2198. for (int j = 0; j < 3; j++)
  2199. if (!ApproximatelyEqual(m1.m_matrix[i, j], m2.m_matrix[i, j]))
  2200. return false;
  2201. return true;
  2202. }
  2203. public static Matrix3 operator *(Matrix3 m1, Matrix3 m2)
  2204. {
  2205. double a, b, c, d, e, f, g, h, i;
  2206. //note: temps needed so that x.multiply(x,y) works OK.
  2207. a = m1.m_matrix[0, 0] * m2.m_matrix[0, 0] + m1.m_matrix[0, 1] * m2.m_matrix[1, 0] + m1.m_matrix[0, 2] * m2.m_matrix[2, 0];
  2208. b = m1.m_matrix[0, 0] * m2.m_matrix[0, 1] + m1.m_matrix[0, 1] * m2.m_matrix[1, 1] + m1.m_matrix[0, 2] * m2.m_matrix[2, 1];
  2209. c = m1.m_matrix[0, 0] * m2.m_matrix[0, 2] + m1.m_matrix[0, 1] * m2.m_matrix[1, 2] + m1.m_matrix[0, 2] * m2.m_matrix[2, 2];
  2210. d = m1.m_matrix[1, 0] * m2.m_matrix[0, 0] + m1.m_matrix[1, 1] * m2.m_matrix[1, 0] + m1.m_matrix[1, 2] * m2.m_matrix[2, 0];
  2211. e = m1.m_matrix[1, 0] * m2.m_matrix[0, 1] + m1.m_matrix[1, 1] * m2.m_matrix[1, 1] + m1.m_matrix[1, 2] * m2.m_matrix[2, 1];
  2212. f = m1.m_matrix[1, 0] * m2.m_matrix[0, 2] + m1.m_matrix[1, 1] * m2.m_matrix[1, 2] + m1.m_matrix[1, 2] * m2.m_matrix[2, 2];
  2213. g = m1.m_matrix[2, 0] * m2.m_matrix[0, 0] + m1.m_matrix[2, 1] * m2.m_matrix[1, 0] + m1.m_matrix[2, 2] * m2.m_matrix[2, 0];
  2214. h = m1.m_matrix[2, 0] * m2.m_matrix[0, 1] + m1.m_matrix[2, 1] * m2.m_matrix[1, 1] + m1.m_matrix[2, 2] * m2.m_matrix[2, 1];
  2215. i = m1.m_matrix[2, 0] * m2.m_matrix[0, 2] + m1.m_matrix[2, 1] * m2.m_matrix[1, 2] + m1.m_matrix[2, 2] * m2.m_matrix[2, 2];
  2216. // fill data
  2217. Matrix3 ret = new Matrix3();
  2218. ret.m_matrix = new double[3, 3];
  2219. ret.m_matrix[0, 0] = a;
  2220. ret.m_matrix[0, 1] = b;
  2221. ret.m_matrix[0, 2] = c;
  2222. ret.m_matrix[1, 0] = d;
  2223. ret.m_matrix[1, 1] = e;
  2224. ret.m_matrix[1, 2] = f;
  2225. ret.m_matrix[2, 0] = g;
  2226. ret.m_matrix[2, 1] = h;
  2227. ret.m_matrix[2, 2] = i;
  2228. return ret;
  2229. }
  2230. public static Matrix3 operator *(Matrix3 m1, double s)
  2231. {
  2232. Matrix3 ret = new Matrix3();
  2233. for (int i = 0; i < 3; i++)
  2234. for (int j = 0; j < 3; j++)
  2235. {
  2236. ret.m_matrix[i, j] = m1.m_matrix[i, j] * s;
  2237. }
  2238. return ret;
  2239. }
  2240. public static Matrix3 operator -(Matrix3 m1, Matrix3 m2)
  2241. {
  2242. Matrix3 ret = new Matrix3();
  2243. for (int i = 0; i < 3; i++)
  2244. for (int j = 0; j < 3; j++)
  2245. {
  2246. ret.m_matrix[i, j] = m1.m_matrix[i, j] - m2.m_matrix[i, j];
  2247. }
  2248. return ret;
  2249. }
  2250. public static Matrix3 operator +(Matrix3 m1, Matrix3 m2)
  2251. {
  2252. Matrix3 ret = new Matrix3();
  2253. for (int i = 0; i < 3; i++)
  2254. for (int j = 0; j < 3; j++)
  2255. {
  2256. ret.m_matrix[i, j] = m1.m_matrix[i, j] + m2.m_matrix[i, j];
  2257. }
  2258. return ret;
  2259. }
  2260. public static bool operator !=(Matrix3 m1, Matrix3 m2)
  2261. {
  2262. return !(m1 == m2);
  2263. }
  2264. #endregion
  2265. #region static memebers
  2266. public static Matrix3 Null
  2267. {
  2268. get
  2269. {
  2270. Matrix3 m = new Matrix3();
  2271. m.m_null = true;
  2272. m.m_matrix = new double[,]{
  2273. {0, 0, 0},
  2274. {0, 0, 0},
  2275. {0, 0, 0}
  2276. };
  2277. return m;
  2278. }
  2279. }
  2280. public static Matrix3 Identity
  2281. {
  2282. get
  2283. {
  2284. Matrix3 m = new Matrix3();
  2285. m.m_matrix = new double[,]{
  2286. {1, 0, 0},
  2287. {0, 1, 0},
  2288. {0, 0, 1}
  2289. };
  2290. return m;
  2291. }
  2292. }
  2293. #endregion
  2294. #region INullable Members
  2295. public bool IsNull
  2296. {
  2297. get { return m_matrix == null | m_null; }
  2298. }
  2299. #endregion
  2300. #region IEquatable<Matrix3> Members
  2301. public bool Equals(Matrix3 matrix)
  2302. {
  2303. return this == matrix;
  2304. }
  2305. public override bool Equals(object obj)
  2306. {
  2307. if (obj is Matrix3)
  2308. return base.Equals((Matrix3)obj);
  2309. else return false;
  2310. }
  2311. public override int GetHashCode()
  2312. {
  2313. return base.GetHashCode();
  2314. }
  2315. #endregion
  2316. public Matrix3 Clone()
  2317. {
  2318. Matrix3 matrix = new Matrix3();
  2319. matrix.m_matrix = new double[3, 3];
  2320. matrix.Data = Data;
  2321. return matrix;
  2322. }
  2323. }
  2324. #endregion
  2325. #region Transform definition
  2326. //[System.Diagnostics.DebuggerDisplay("{format(8)}", Name = "Transform")]
  2327. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  2328. public struct Transform : INullable, IEquatable<Transform>
  2329. {
  2330. private Matrix3 rotation;
  2331. private Vector translation;
  2332. private double scale;
  2333. private bool m_null;
  2334. private string format(byte dig)
  2335. {
  2336. Transform t = RoundTo(this, dig);
  2337. return string.Empty;
  2338. }
  2339. public Transform(double[] data): this()
  2340. {
  2341. if (rotation.IsNull)
  2342. rotation = Matrix3.Identity;
  2343. rotation.RowMajor_set(data);
  2344. translation = new Vector(data[9], data[10], data[11]);
  2345. scale = data[12];
  2346. }
  2347. public double[] Data
  2348. {
  2349. get {
  2350. double[] value = new double[16];
  2351. //Rotation data
  2352. double[] rot = rotation.RowMajor_get();
  2353. for (int i = 0; i < rot.Length; i++)
  2354. value[i] = rot[i];
  2355. //Translation data
  2356. value[9] = translation.x;
  2357. value[10] = translation.y;
  2358. value[11] = translation.z;
  2359. //scale date
  2360. value[12] = scale; //scaling
  2361. return value;
  2362. }
  2363. set
  2364. {
  2365. //set Rotation data
  2366. rotation.RowMajor_set(value);
  2367. //set Translation data
  2368. translation.x = value[9];
  2369. translation.y = value[10];
  2370. translation.z = value[11];
  2371. //scale date
  2372. scale = value[12];
  2373. }
  2374. }
  2375. public double Scale { get { return scale; }
  2376. //set { scale = value; }
  2377. }
  2378. public Matrix3 Rotation
  2379. {
  2380. get { return rotation; }
  2381. set { rotation = value; }
  2382. }
  2383. public Vector Translation
  2384. {
  2385. get { return translation; }
  2386. set { translation = value; }
  2387. }
  2388. public Transform Inverse
  2389. {
  2390. get
  2391. {
  2392. if (m_null)
  2393. return Null;
  2394. Transform t = Transform.Identity;
  2395. t.Rotation.RowMajor_set(rotation.Inverse.RowMajor_get());
  2396. t.translation = rotation.Inverse.Multiply(translation * -1.0);
  2397. return t;
  2398. }
  2399. }
  2400. public void Multiply(Transform t)
  2401. {
  2402. translation = t.rotation.Multiply(translation) + t.translation;
  2403. rotation.Multiply(t.rotation);
  2404. }
  2405. public Point TransformPoint(Point point)
  2406. {
  2407. return rotation.Multiply(point) + translation;
  2408. }
  2409. public Vector TransformVector(Vector vector)
  2410. {
  2411. return rotation.Multiply(vector);
  2412. }
  2413. public void RotateXAxis(double angle) { rotation.RotateXAxis(angle); }
  2414. public void RotateYAxis(double angle) { rotation.RotateYAxis(angle); }
  2415. public void RotateZAxis(double angle) { rotation.RotateZAxis(angle); }
  2416. #region INullable Members
  2417. public bool IsNull
  2418. {
  2419. get { return m_null || rotation.IsNull || translation.IsNull; }
  2420. }
  2421. #endregion
  2422. #region IEquatable<Transform> Members
  2423. public bool Equals(Transform other)
  2424. {
  2425. throw new Exception("The method or operation is not implemented.");
  2426. }
  2427. #endregion
  2428. #region static members
  2429. public static Transform Null
  2430. {
  2431. get
  2432. {
  2433. Transform t = new Transform();
  2434. t.rotation = Matrix3.Null;
  2435. t.translation = Vector.Null;
  2436. t.m_null = true;
  2437. return t;
  2438. }
  2439. }
  2440. /// <summary>
  2441. /// Returns identity transformation
  2442. /// </summary>
  2443. public static Transform Identity
  2444. {
  2445. get {
  2446. Transform t = new Transform();
  2447. t.rotation = Matrix3.Identity;
  2448. t.translation = new Vector();
  2449. t.scale = 1.0;
  2450. return t;
  2451. }
  2452. }
  2453. #endregion
  2454. public Transform Clone()
  2455. {
  2456. return new Transform(Data);
  2457. }
  2458. }
  2459. #endregion
  2460. #region Basis definition
  2461. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  2462. public struct Basis : INullable
  2463. {
  2464. private Point point;
  2465. private Transform transform;
  2466. private Plane xyPlane;
  2467. private Plane xzPlane;
  2468. private Plane yzPlane;
  2469. private bool m_null;
  2470. public Point Point { get { return point; } }
  2471. public Vector XAxis { get { return transform.Rotation.XAxis; } }
  2472. public Vector YAxis { get { return transform.Rotation.YAxis; } }
  2473. public Vector ZAxis { get { return transform.Rotation.ZAxis; } }
  2474. public Plane XYPlane { get { return xyPlane; } }
  2475. public Plane YZPlane { get { return yzPlane; } }
  2476. public Plane XZPlane { get { return xzPlane; } }
  2477. public Transform Transform { get { return transform; } }
  2478. public Basis(Point point, Vector normal)
  2479. : this()
  2480. {
  2481. this.point = point;
  2482. Vector x = normal.GetPerpVector();
  2483. Vector y = x ^ normal;
  2484. Vector z = normal;
  2485. x.Inverce();
  2486. transform = new Transform();
  2487. transform.Rotation = new Matrix3(x, y, z);
  2488. transform.Translation = new Point()[point];
  2489. xyPlane = new Plane(x, y, point);
  2490. xzPlane = new Plane(x, z, point);
  2491. yzPlane = new Plane(y, z, point);
  2492. }
  2493. public Basis(Point point, Vector X, Vector Y, Vector Z)
  2494. : this()
  2495. {
  2496. this.point = point;
  2497. transform = new Transform();
  2498. transform.Rotation = new Matrix3(X, Y, Z);
  2499. transform.Translation = new Point()[point];
  2500. xyPlane = new Plane(X, Y, point);
  2501. xzPlane = new Plane(X, Z, point);
  2502. yzPlane = new Plane(Y, Z, point);
  2503. }
  2504. public Basis(Point point, double alpha, double beta, double gamma)
  2505. : this()
  2506. {
  2507. this.point = point;
  2508. transform = new Transform();
  2509. transform.Rotation = new Matrix3(alpha, beta, gamma);
  2510. transform.Translation = new Point()[point];
  2511. xyPlane = new Plane(transform.Rotation.XAxis, transform.Rotation.YAxis, point);
  2512. xzPlane = new Plane(transform.Rotation.XAxis, transform.Rotation.ZAxis, point);
  2513. yzPlane = new Plane(transform.Rotation.YAxis, transform.Rotation.ZAxis, point);
  2514. }
  2515. #region INullable Members
  2516. public bool IsNull
  2517. {
  2518. get { return m_null | transform.IsNull; }
  2519. }
  2520. #endregion
  2521. public static Basis STOCK
  2522. {
  2523. get
  2524. {
  2525. Basis u = new Basis();
  2526. u.transform = new Transform();
  2527. Vector x = new Vector(1, 0, 0);
  2528. Vector y = new Vector(0, 1, 0);
  2529. Vector z = new Vector(0, 0, 1);
  2530. u.transform.Rotation = Matrix3.Identity;
  2531. u.xyPlane = new Plane(x, y, new Point());
  2532. u.xzPlane = new Plane(x, z, new Point());
  2533. u.yzPlane = new Plane(y, z, new Point());
  2534. return u;
  2535. }
  2536. }
  2537. public static Basis Null
  2538. {
  2539. get
  2540. {
  2541. Basis u = new Basis();
  2542. u.m_null = true;
  2543. u.transform = Transform.Null;
  2544. u.xyPlane = Plane.Null;
  2545. u.xzPlane = Plane.Null;
  2546. u.yzPlane = Plane.Null;
  2547. return u;
  2548. }
  2549. }
  2550. public Vector ToSTOCK(Vector vector)
  2551. {
  2552. return vector[transform.Inverse];
  2553. }
  2554. public Point ToSTOCK(Point point)
  2555. {
  2556. return point[transform.Inverse];
  2557. }
  2558. public Vector ToUCS(Vector vector)
  2559. {
  2560. return vector[transform];
  2561. }
  2562. public Point ToUCS(Point point)
  2563. {
  2564. return point[transform];
  2565. }
  2566. internal Basis Clone()
  2567. {
  2568. return new Basis(point, XAxis, YAxis, ZAxis);
  2569. }
  2570. }
  2571. #endregion
  2572. #region Beam definition
  2573. public struct Beam : IEquatable<Beam>, INullable
  2574. {
  2575. private Vector _direction;
  2576. private Point _point;
  2577. private bool m_null;
  2578. #region IEquatable<Beam> Members
  2579. public override bool Equals(object obj)
  2580. {
  2581. return base.Equals(obj);
  2582. }
  2583. public bool Equals(Beam point)
  2584. {
  2585. return this == point;
  2586. }
  2587. public override int GetHashCode()
  2588. {
  2589. return _direction.GetHashCode() ^ _point.GetHashCode() ^ m_null.GetHashCode();
  2590. }
  2591. #endregion
  2592. #region operators
  2593. public static bool operator ==(Beam b1, object b2)
  2594. {
  2595. if (b2 == default(object))
  2596. return false;
  2597. return b1 == (Beam)b2;
  2598. }
  2599. public static bool operator !=(Beam b1, object b2)
  2600. {
  2601. if (b2 == default(object))
  2602. return true;
  2603. return b1 != (Beam)b2;
  2604. }
  2605. public static bool operator ==(Beam b1, Beam b2)
  2606. {
  2607. return
  2608. b1.Point == b2.Point
  2609. &&
  2610. b1.Direction == b2.Direction;
  2611. }
  2612. public static bool operator !=(Beam b1, Beam b2)
  2613. {
  2614. return !(b1 == b2);
  2615. }
  2616. #endregion
  2617. public Vector Direction { get { return _direction; } }
  2618. public Point Point { get { return _point; } }
  2619. public Beam(Point point, Vector direction)
  2620. : this()
  2621. {
  2622. m_null = false;
  2623. _point = point;
  2624. _direction = direction;
  2625. }
  2626. #region static members
  2627. public static Beam Null
  2628. {
  2629. get
  2630. {
  2631. Beam p = new Beam();
  2632. p._point = Point.Null;
  2633. p.m_null = true;
  2634. return p;
  2635. }
  2636. }
  2637. public static bool IsSame(Beam beam1, Beam beam2)
  2638. {
  2639. if (beam2.Direction.IsParallelTo(beam1.Direction))
  2640. {
  2641. if (beam2.Point - beam1.Point == beam1.Direction)
  2642. return true;
  2643. if (beam1.Point - beam2.Point == beam1.Direction)
  2644. return true;
  2645. }
  2646. return true;
  2647. }
  2648. public static bool Intersect(Beam beam1, Beam beam2, out Point point)
  2649. {
  2650. point = default(Point);
  2651. if (!IsSame(beam1, beam2))
  2652. {
  2653. if (beam1.Point == beam2.Point)
  2654. {
  2655. point = beam2.Point;
  2656. return true;
  2657. }
  2658. double ortLength = 0.0001;
  2659. Vector A = new Vector(beam1.Point.x, beam1.Point.y, beam1.Point.z);
  2660. Vector B = beam1.Point - beam2.Point[beam1.Direction.GetNormalized() * ortLength];
  2661. Vector C = new Vector(beam2.Point.x, beam2.Point.y, beam2.Point.z);
  2662. Vector D = beam2.Point - beam2.Point[beam2.Direction.GetNormalized() * ortLength];
  2663. double s;
  2664. if (!ApproximatelyEqual((D.x * B.y) - (D.y * B.x), 0))
  2665. {
  2666. s = (C.y * B.x) - (A.y * B.x) - (C.x * B.y) + (A.x * B.y);
  2667. if (ApproximatelyEqual(s, 0))
  2668. s = 0;
  2669. if (ApproximatelyEqual((D.x * B.y) - (D.y * B.x), 0))
  2670. s = 0;
  2671. else
  2672. s /= (D.x * B.y) - (D.y * B.x);
  2673. s = 1 - s;
  2674. C = C + (D * (1 - s));
  2675. point = new Point(C.x, C.y, C.z);
  2676. }
  2677. else
  2678. if (!ApproximatelyEqual((D.x * B.z) - (D.z * B.x), 0))
  2679. {
  2680. s = (C.z * B.x) - (A.z * B.x) - (C.x * B.z) + (A.x * B.z);
  2681. if (ApproximatelyEqual(s, 0))
  2682. s = 0;
  2683. if (ApproximatelyEqual((D.x * B.z) - (D.z * B.x), 0))
  2684. s = 0;
  2685. else
  2686. s /= (D.x * B.z) - (D.z * B.x);
  2687. s = 1 - s;
  2688. C = C + (D * (1 - s));
  2689. point = new Point(C.x, C.y, C.z);
  2690. }
  2691. else
  2692. if (!ApproximatelyEqual((D.y * B.z) - (D.z * B.y), 0))
  2693. {
  2694. s = (C.z * B.y) - (A.z * B.y) - (C.y * B.z) + (A.y * B.z);
  2695. if (ApproximatelyEqual(s, 0))
  2696. s = 0;
  2697. if (ApproximatelyEqual((D.y * B.z) - (D.z * B.y), 0))
  2698. s = 0;
  2699. else
  2700. s /= (D.y * B.z) - (D.z * B.y);
  2701. s = 1 - s;
  2702. C = C + (D * (1 - s));
  2703. point = new Point(C.x, C.y, C.z);
  2704. }
  2705. return true;
  2706. }
  2707. else return false;
  2708. }
  2709. #endregion
  2710. #region INullable Members
  2711. public bool IsNull { get { return m_null || _point.IsNull || _direction.IsNull; } }
  2712. #endregion
  2713. }
  2714. #endregion
  2715. #region Curve definition
  2716. public struct Curve
  2717. {
  2718. private int _cType;
  2719. public int CType
  2720. {
  2721. get { return _cType; }
  2722. set { _cType = value; }
  2723. }
  2724. }
  2725. #endregion
  2726. public class Link<T>
  2727. {
  2728. private T _value = default(T);
  2729. private Link<T> _Next = null;
  2730. private Link<T> _Prev = null;
  2731. /// <summary>
  2732. /// Возвращает звено, в котором содержиться елемент
  2733. /// </summary>
  2734. /// <param name="element">Элемент</param>
  2735. /// <returns></returns>
  2736. private Link<T> _chain(T element)
  2737. {
  2738. if (element == null)
  2739. return null;
  2740. Link<T> _p = _Prev;
  2741. Link<T> _n = _Next;
  2742. if (element.Equals(_value))
  2743. return this;
  2744. while (!(_p ==null | _n == null))
  2745. {
  2746. if (_p != null)
  2747. {
  2748. if (element.Equals(_p._value))
  2749. {
  2750. return _p;
  2751. }
  2752. _p = _p._Prev;
  2753. }
  2754. if (_n != null)
  2755. {
  2756. if (element.Equals(_n._value))
  2757. {
  2758. return _n;
  2759. }
  2760. _n = _n._Next;
  2761. }
  2762. }
  2763. return null;
  2764. }
  2765. /// <summary>
  2766. /// Исключает текущее звено из цепи
  2767. /// </summary>
  2768. public void Exclude()
  2769. {
  2770. if (!IsBound)
  2771. {
  2772. _Next._Prev = _Prev._Next;
  2773. return;
  2774. }
  2775. if (IsLBound)
  2776. {
  2777. _Next._Prev = null;
  2778. return;
  2779. }
  2780. if (IsRBound)
  2781. {
  2782. _Prev._Next = null;
  2783. return;
  2784. }
  2785. this._Prev = null;
  2786. this._Next = null;
  2787. }
  2788. /// <summary>
  2789. /// Добавляет элемент в последовательность
  2790. /// </summary>
  2791. /// <param name="element">Добавляемый элемент</param>
  2792. /// <param name="after">В зависимости от значения, перед или после текущего элемента цепи</param>
  2793. public void Include(T element, bool after)
  2794. {
  2795. Link<T> el = new Link<T>();
  2796. el._value = element;
  2797. if (after)
  2798. {
  2799. if (IsRBound)
  2800. {
  2801. _Next = el;
  2802. el._Prev = this;
  2803. }
  2804. if (IsLBound)
  2805. {
  2806. el._Prev = _Next;
  2807. _Next = el;
  2808. el._Prev = this;
  2809. }
  2810. }
  2811. }
  2812. /// <summary>
  2813. /// Перемещает текущее звено после заданного или перед ним
  2814. /// </summary>
  2815. /// <param name="chain">Заданное звено</param>
  2816. public void MoveTo(Link<T> chain, bool after) { }
  2817. /// <summary>
  2818. /// True, если звено имеет неопределенное значение
  2819. /// </summary>
  2820. public bool IsNull { get { return _value != null ? _value.Equals(default(T)) : true; } }
  2821. /// <summary>
  2822. /// Значение
  2823. /// </summary>
  2824. public T Value { get { return _value; } }
  2825. /// <summary>
  2826. /// Определяет звено, в котором находится элемент
  2827. /// </summary>
  2828. /// <param name="element"></param>
  2829. /// <returns></returns>
  2830. public Link<T> Chain(T element) { return _chain(element); }
  2831. public bool IsRBound { get { return _Next == null; } }
  2832. public bool IsLBound { get { return _Prev == null; } }
  2833. public bool IsBound { get { return IsRBound || IsLBound; } }
  2834. }
  2835. public class FlatPolygon
  2836. {
  2837. private double triangSquareGeron2(Point p1, Point p2, Point p3)
  2838. {
  2839. double a = Length2(p1, p2);
  2840. double b = Length2(p2, p3);
  2841. double c = Length2(p1, p3);
  2842. double p = 0.5 * (a + b + c);
  2843. if ((p - a < 0) | (p - b < 0) | (p - c < 0))
  2844. return double.NaN;
  2845. return p * (p - a) * (p - b) * (p - c);
  2846. }
  2847. private void getExtremumIndexs(ref Point[] points, byte dwFlag, out int minIndex, out int maxIndex)
  2848. {
  2849. minIndex = -1;
  2850. maxIndex = -1;
  2851. if (dwFlag < 1 | dwFlag > 3 | points.Length <1)
  2852. return;
  2853. double minVal = default(double);
  2854. double maxVal = default(double);
  2855. /// set initial values
  2856. ///
  2857. minIndex = 0;
  2858. maxIndex = 0;
  2859. /// set x component
  2860. ///
  2861. if (dwFlag == 1)
  2862. {
  2863. minVal = points[0].x;
  2864. maxVal = points[0].x;
  2865. }
  2866. /// set y component
  2867. ///
  2868. if (dwFlag == 2)
  2869. {
  2870. minVal = points[0].y;
  2871. maxVal = points[0].y;
  2872. }
  2873. /// set z component
  2874. ///
  2875. if (dwFlag == 2)
  2876. {
  2877. minVal = points[0].z;
  2878. maxVal = points[0].z;
  2879. }
  2880. /// scan throug all poins
  2881. ///
  2882. for (int i = 1; i < points.Length; i++)
  2883. {
  2884. /// test x component
  2885. ///
  2886. if (dwFlag == 1)
  2887. {
  2888. if (minVal > points[i].x)
  2889. {
  2890. minIndex = i;
  2891. minVal = points[i].x;
  2892. }
  2893. if (maxVal < points[i].x)
  2894. {
  2895. maxIndex = i;
  2896. maxVal = points[i].x;
  2897. }
  2898. continue;
  2899. }
  2900. /// test y component
  2901. ///
  2902. if (dwFlag == 2)
  2903. {
  2904. if (minVal > points[i].y)
  2905. {
  2906. minIndex = i;
  2907. minVal = points[i].y;
  2908. }
  2909. if (maxVal < points[i].y)
  2910. {
  2911. maxIndex = i;
  2912. maxVal = points[i].y;
  2913. }
  2914. continue;
  2915. }
  2916. /// test z component
  2917. ///
  2918. if (dwFlag == 3)
  2919. {
  2920. if (minVal > points[i].z)
  2921. {
  2922. minIndex = i;
  2923. minVal = points[i].z;
  2924. }
  2925. if (maxVal < points[i].z)
  2926. {
  2927. maxIndex = i;
  2928. maxVal = points[i].z;
  2929. }
  2930. continue;
  2931. }
  2932. }
  2933. }
  2934. private bool getExtremumIndexs(IEnumerator<Point> points, byte dwFlag, out Point minPoint, out Point maxPoint)
  2935. {
  2936. minPoint = default(Point);
  2937. maxPoint = default(Point);
  2938. points.Reset();
  2939. if (dwFlag < 1 | dwFlag > 3 | !points.MoveNext())
  2940. return false;
  2941. double minVal = default(double);
  2942. double maxVal = default(double);
  2943. /// set x component
  2944. ///
  2945. if (dwFlag == 1)
  2946. {
  2947. minVal = points.Current.x;
  2948. maxVal = points.Current.x;
  2949. minPoint = points.Current;
  2950. maxPoint = points.Current;
  2951. }
  2952. /// set y component
  2953. ///
  2954. if (dwFlag == 2)
  2955. {
  2956. minVal = points.Current.y;
  2957. maxVal = points.Current.y;
  2958. minPoint = points.Current;
  2959. maxPoint = points.Current;
  2960. }
  2961. /// set z component
  2962. ///
  2963. if (dwFlag == 2)
  2964. {
  2965. minVal = points.Current.z;
  2966. maxVal = points.Current.z;
  2967. minPoint = points.Current;
  2968. maxPoint = points.Current;
  2969. }
  2970. int counter = 0;
  2971. /// scan throug all poins
  2972. ///
  2973. while (points.MoveNext())
  2974. {
  2975. counter++;
  2976. /// test x component
  2977. ///
  2978. if (dwFlag == 1)
  2979. {
  2980. if (minVal > points.Current.x)
  2981. {
  2982. minVal = points.Current.x;
  2983. minPoint = points.Current;
  2984. }
  2985. if (maxVal < points.Current.x)
  2986. {
  2987. maxPoint = points.Current;
  2988. maxVal = points.Current.x;
  2989. }
  2990. continue;
  2991. }
  2992. /// test y component
  2993. ///
  2994. if (dwFlag == 2)
  2995. {
  2996. if (minVal > points.Current.y)
  2997. {
  2998. minVal = points.Current.y;
  2999. minPoint = points.Current;
  3000. }
  3001. if (maxVal < points.Current.y)
  3002. {
  3003. maxPoint = points.Current;
  3004. maxVal = points.Current.y;
  3005. }
  3006. continue;
  3007. }
  3008. /// test z component
  3009. ///
  3010. if (dwFlag == 3)
  3011. {
  3012. if (minVal > points.Current.z)
  3013. {
  3014. minVal = points.Current.z;
  3015. minPoint = points.Current;
  3016. }
  3017. if (maxVal < points.Current.z)
  3018. {
  3019. maxPoint = points.Current;
  3020. maxVal = points.Current.z;
  3021. }
  3022. continue;
  3023. }
  3024. }
  3025. return counter > 0;
  3026. }
  3027. /// <summary>
  3028. /// returns true if set contains only 2 points l and r
  3029. /// </summary>
  3030. /// <param name="iEnum">point set</param>
  3031. /// <param name="l"></param>
  3032. /// <param name="r"></param>
  3033. /// <returns></returns>
  3034. private bool compareSetLR (IEnumerator<Point> iEnum, Point l, Point r)
  3035. {
  3036. if (iEnum == null)
  3037. throw new ArgumentNullException();
  3038. iEnum.Reset();
  3039. if (iEnum.MoveNext())
  3040. {
  3041. if ((l != iEnum.Current) & r != iEnum.Current)
  3042. return false;
  3043. }
  3044. if (iEnum.MoveNext())
  3045. {
  3046. if ((l != iEnum.Current) & r != iEnum.Current)
  3047. return false;
  3048. }
  3049. return !iEnum.MoveNext();
  3050. }
  3051. private Point[] qConvex(IEnumerable<Point> values, Point l, Point r)
  3052. {
  3053. if (compareSetLR(values.GetEnumerator(), l, r))
  3054. return new Point[] { l, r };
  3055. else
  3056. {
  3057. Point h = default(Point);
  3058. Dictionary<bool, IList<Point>> conv = new Dictionary<bool, IList<Point>>();
  3059. /// upper part
  3060. ///
  3061. conv.Add(true, new List<Point>());
  3062. /// lower part
  3063. ///
  3064. conv.Add(false, new List<Point>());
  3065. /// collect athother points (sort points on parts)
  3066. ///
  3067. if (!getFarsetPoint(values, l, r, out h))
  3068. if (l[r].Length2() > Accuracy)
  3069. throw new InvalidOperationException("far point not found. values is line");
  3070. else
  3071. {
  3072. if (!getExtremumIndexs(values.GetEnumerator() as IEnumerator<Point>, 1, out l, out r))
  3073. throw new InvalidOperationException("far point not found. values is line");
  3074. if (!getFarsetPoint(values, l, r, out h))
  3075. throw new InvalidOperationException("far point not found. values is line");
  3076. }
  3077. // return new Point[0];
  3078. foreach (Point point in values)
  3079. {
  3080. bool isExists = false;
  3081. if (!(Gm.iLeftOrRight(point, l, h) < 0))
  3082. {
  3083. for (int i = 0; i < conv[true].Count; i++)
  3084. {
  3085. if (conv[true][i] == point)
  3086. {
  3087. isExists = true;
  3088. break;
  3089. }
  3090. }
  3091. if (!isExists)
  3092. conv[true].Add(point);
  3093. continue;
  3094. }
  3095. if (!(Gm.iLeftOrRight(point, h, r) > 0))
  3096. {
  3097. for (int i = 0; i < conv[false].Count; i++)
  3098. {
  3099. if (conv[false][i] == point)
  3100. {
  3101. isExists = true;
  3102. break;
  3103. }
  3104. }
  3105. if (!isExists)
  3106. conv[false].Add(point);
  3107. continue;
  3108. }
  3109. /// auxillary step
  3110. /// ?
  3111. //double dRet = Gm.iLeftOrRight(point, l,r) ;
  3112. //if (Math.Abs( dRet ) < Accuracy)
  3113. // continue;
  3114. //if (dRet > 0)
  3115. // conv[true].Add(point);
  3116. //else
  3117. // conv[false].Add(point);
  3118. }
  3119. List<Point> ret = new List<Point>();
  3120. if (conv[true].Count > 0)
  3121. ret.AddRange(qConvex(conv[true], l, h));
  3122. ///remove duplicat-point
  3123. ///
  3124. for (int i = 0; i < conv[false].Count; i++)
  3125. {
  3126. if (conv[false][i] == h)
  3127. {
  3128. conv[false].RemoveAt(i);
  3129. break;
  3130. }
  3131. }
  3132. if (conv[false].Count > 0)
  3133. ret.AddRange(qConvex(conv[false], h, r));
  3134. return ret.ToArray();
  3135. }
  3136. }
  3137. private bool getFarsetPoint(IEnumerable<Point> values, Point l, Point r, out Point tPoint)
  3138. {
  3139. tPoint = default(Point);
  3140. ///get a point enumerator
  3141. ///
  3142. IEnumerator<Point> pointEnum = values.GetEnumerator();
  3143. /// prepare values
  3144. ///
  3145. pointEnum.Reset();
  3146. if (!pointEnum.MoveNext())
  3147. return false;
  3148. double max = Math.Abs( TriangSquareGeron(pointEnum.Current, l, r));
  3149. /// add first point to set
  3150. ///
  3151. List<Point> maxPts = new List<Point>();
  3152. if (!double.IsNaN(max) && !(max < Accuracy))
  3153. maxPts.Add(pointEnum.Current);
  3154. ///enum another points
  3155. ///
  3156. while (pointEnum.MoveNext())
  3157. {
  3158. if (pointEnum.Current == l || pointEnum.Current == r)
  3159. continue;
  3160. double temp = RoundTo(TriangSquareGeron(pointEnum.Current, l, r), 5);
  3161. if (!(temp < max) & RoundTo(System.Math.Abs(temp - max), 5) > Accuracy)
  3162. {
  3163. /// clear list and add new value
  3164. if (temp > max)
  3165. maxPts.Clear();
  3166. max = temp;
  3167. maxPts.Add(pointEnum.Current);
  3168. }
  3169. }
  3170. if(maxPts.Count == 0)
  3171. return false;
  3172. Vector v1 = new Vector(0,1,0);
  3173. Vector v2 = maxPts[0] - l;
  3174. int minI = 0;
  3175. double min = v1.AngleTo(v2);
  3176. for (int i = 1; i < maxPts.Count; i++)
  3177. {
  3178. v2 = maxPts[i] - l;
  3179. double temp;
  3180. if (min > (temp = v1.AngleTo(v2)))
  3181. {
  3182. minI = i;
  3183. min = temp;
  3184. }
  3185. }
  3186. tPoint = maxPts[minI];
  3187. return true;
  3188. }
  3189. public void Convex(ref Point[] points, out IList<Point> result)
  3190. {
  3191. result = null;
  3192. try
  3193. {
  3194. int maxX, minX;
  3195. getExtremumIndexs(ref points, 1, out minX, out maxX);
  3196. if (maxX > -1 & minX > -1)
  3197. {
  3198. Point L0 = points[minX];
  3199. Point R0 = new Point(L0.x, L0.y - Accuracy, L0.z);
  3200. result = new List<Point>();
  3201. ((List<Point>)result).AddRange(qConvex(points, L0, R0));
  3202. result.Remove(R0);
  3203. }
  3204. }
  3205. catch (InvalidOperationException) { result = null; }
  3206. }
  3207. public bool DetectRationalBox(bool AllignByXAsix, ref Point[] convex)
  3208. {
  3209. throw new NotFiniteNumberException();
  3210. }
  3211. }
  3212. }
  3213. }