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

/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

Large files files are truncated, but you can click here to view the full file

  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;

Large files files are truncated, but you can click here to view the full file