PageRenderTime 70ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/fpTransform/fpTransform/Module/TransformModule/Gm.cs

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