PageRenderTime 63ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/fpFormat/FormatModule/Gm.cs

https://bitbucket.org/kinna/itadp033_kucher_inna
C# | 3645 lines | 2872 code | 432 blank | 341 comment | 350 complexity | 728b2e2b912305f0d0cb73da19a31272 MD5 | raw file
Possible License(s): BSD-3-Clause

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. using System.Runtime.Serialization;
  8. using SoftServe.TaskElementary.FormatModule;
  9. namespace geometry
  10. {
  11. public static class Gm
  12. {
  13. public enum DecartPosition
  14. {
  15. Origin = 0,
  16. At1 = 1,
  17. At2 = 2,
  18. At3 = 3,
  19. At4 = 4,
  20. AtX_PlusY = 5,
  21. AtX_MinusY = 6,
  22. AtY_PlusX = 7,
  23. AtY_MinusX = 8
  24. }
  25. #region Common
  26. public static double Accuracy { get { return 0.0000001; } }
  27. public static uint MaxDigits { get { return 7; } }
  28. public static bool ApproximatelyEqual(double d1, double d2, double tol)
  29. {
  30. return (Math.Abs(d1 - d2) < tol);
  31. }
  32. public static bool ApproximatelyEqual(double d1, double d2)
  33. {
  34. return (Math.Abs(d1 - d2) < Accuracy);
  35. }
  36. public static bool ApproximatelyEqual(float d1, float d2, float tol)
  37. {
  38. return (Math.Abs(d1 - d2) < tol);
  39. }
  40. public static bool ApproximatelyEqual(float d1, float d2)
  41. {
  42. return (Math.Abs(d1 - d2) < Accuracy);
  43. }
  44. public static bool Factor(uint digits, out double factor1, out double factor2)
  45. {
  46. factor1 = 1;
  47. factor2 = 1;
  48. if (digits > MaxDigits)
  49. throw new ArgumentException("Argument exception: digits");
  50. switch (digits)
  51. {
  52. case 0:
  53. factor1 = factor2 = 0;
  54. return true;
  55. case 1:
  56. factor1 = 0.1;
  57. factor2 = 10;
  58. break;
  59. case 2:
  60. factor1 = 0.01;
  61. factor2 = 100;
  62. break;
  63. case 3:
  64. factor1 = 0.001;
  65. factor2 = 1000;
  66. break;
  67. case 4:
  68. factor1 = 0.0001;
  69. factor2 = 10000;
  70. break;
  71. case 5:
  72. factor1 = 0.00001;
  73. factor2 = 100000;
  74. break;
  75. default:
  76. for (int i = 0; i < digits; i++)
  77. {
  78. factor1 *= 0.1;
  79. factor2 *= 10;
  80. }
  81. break;
  82. }
  83. return false;
  84. }
  85. public static bool Factor(uint digits, out float factor1, out float factor2)
  86. {
  87. factor1 = 1;
  88. factor2 = 1;
  89. if (digits > MaxDigits)
  90. throw new ArgumentException("Argument exception: digits");
  91. switch (digits)
  92. {
  93. case 0:
  94. factor1 = factor2 = 0f;
  95. return true;
  96. case 1:
  97. factor1 = 0.1f;
  98. factor2 = 10f;
  99. break;
  100. case 2:
  101. factor1 = 0.01f;
  102. factor2 = 100f;
  103. break;
  104. case 3:
  105. factor1 = 0.001f;
  106. factor2 = 1000f;
  107. break;
  108. case 4:
  109. factor1 = 0.0001f;
  110. factor2 = 10000f;
  111. break;
  112. case 5:
  113. factor1 = 0.00001f;
  114. factor2 = 100000f;
  115. break;
  116. default:
  117. for (int i = 0; i < digits; i++)
  118. {
  119. factor1 *= 0.1f;
  120. factor2 *= 10f;
  121. }
  122. break;
  123. }
  124. return false;
  125. }
  126. public static double DegToRad(float angle) { return angle * Math.PI / 180; }
  127. public static double DegToRad(double angle) { return angle * Math.PI / 180; }
  128. public static double RadToDeg(float angle) { return angle * 180 / Math.PI; }
  129. public static double RadToDeg(double angle) { return angle * 180/ Math.PI; }
  130. public static double RoundTo(float value, uint digits)
  131. {
  132. float factor1 = default(float);
  133. float factor2 = factor1;
  134. float ret;
  135. Factor(digits, out factor1, out factor2);
  136. if (Factor(digits, out factor1, out factor2))
  137. ret = (int)value;
  138. else
  139. ret = ((int)(value * factor2)) * factor1;
  140. return ret;
  141. }
  142. public static double RoundTo(double value, uint digits)
  143. {
  144. double factor1 = default(double);
  145. double factor2 = factor1;
  146. double ret;
  147. Factor(digits, out factor1, out factor2);
  148. if (Factor(digits, out factor1, out factor2))
  149. ret = (int)value;
  150. else
  151. ret = ((int)(value * factor2)) * factor1;
  152. return ret;
  153. }
  154. public static Vector RoundTo(Vector value, uint digits)
  155. {
  156. double factor1 = default(double);
  157. double factor2 = factor1;
  158. Vector ret = new Vector();
  159. if (Factor(digits, out factor1, out factor2))
  160. {
  161. ret.x = (int)value.x;
  162. ret.y = (int)value.y;
  163. ret.z = (int)value.z;
  164. }
  165. else
  166. {
  167. ret.x = ((int)(value.x * factor2)) * factor1;
  168. ret.y = ((int)(value.y * factor2)) * factor1;
  169. ret.z = ((int)(value.z * factor2)) * factor1;
  170. }
  171. return ret;
  172. }
  173. public static Point RoundTo(Point value, uint digits)
  174. {
  175. double factor1 = default(double);
  176. double factor2 = factor1;
  177. Point ret = new Point();
  178. Factor(digits, out factor1, out factor2);
  179. if (Factor(digits, out factor1, out factor2))
  180. {
  181. ret.x = (int)value.x;
  182. ret.y = (int)value.y;
  183. ret.z = (int)value.z;
  184. }
  185. else
  186. {
  187. ret.x = ((int)(value.x * factor2)) * factor1;
  188. ret.y = ((int)(value.y * factor2)) * factor1;
  189. ret.z = ((int)(value.z * factor2)) * factor1;
  190. }
  191. return ret;
  192. }
  193. public static Quaterion RoundTo(Quaterion value, uint digits)
  194. {
  195. double factor1 = default(double);
  196. double factor2 = factor1;
  197. Quaterion ret = new Quaterion();
  198. Factor(digits, out factor1, out factor2);
  199. if (Factor(digits, out factor1, out factor2))
  200. {
  201. ret.Vector = new Vector((int)value.Vector.x, (int)value.Vector.y, (int)value.Vector.z);
  202. ret.W = (int)value.W;
  203. }
  204. else
  205. {
  206. ret.Vector = new Vector(((int)(value.Vector.x * factor2)) * factor1, ((int)(value.Vector.y * factor2)) * factor1, ((int)(value.Vector.z * factor2)) * factor1);
  207. ret.W = ((int)(value.W * factor2)) * factor1;
  208. }
  209. return ret;
  210. }
  211. public static Matrix3 RoundTo(Matrix3 value, uint digits)
  212. {
  213. double factor1 = default(double);
  214. double factor2 = factor1;
  215. double[] data = value.Data;
  216. //Matrix3 ret = new Matrix3();
  217. Factor(digits, out factor1, out factor2);
  218. if (Factor(digits, out factor1, out factor2))
  219. {
  220. for (int i = 0; i < data.Length; i++)
  221. data[i] = (int)data[i];
  222. }
  223. else
  224. {
  225. for (int i = 0; i < data.Length; i++)
  226. data[i] = ((int)(data[i] * factor2)) * factor1;
  227. }
  228. return new Matrix3(data);
  229. }
  230. public static Transform RoundTo(Transform value, uint digits)
  231. {
  232. double factor1 = default(double);
  233. double factor2 = factor1;
  234. double[] data = value.Data;
  235. Transform ret = new Transform();
  236. Factor(digits, out factor1, out factor2);
  237. if (Factor(digits, out factor1, out factor2))
  238. {
  239. for (int i = 0; i < data.Length; i++)
  240. data[i] = (int)data[i];
  241. }
  242. else
  243. {
  244. for (int i = 0; i < data.Length; i++)
  245. data[i] = ((int)(data[i] * factor2)) * factor1;
  246. }
  247. return new Transform(data);
  248. }
  249. /// <summary>
  250. /// Split double array to vectors
  251. /// </summary>
  252. /// <param name="values"></param>
  253. /// <param name="vDim"></param>
  254. /// <param name="useRound"></param>
  255. /// <param name="digits"></param>
  256. /// <returns></returns>
  257. public static Vector[] SplitToVectors(double[] values, byte vDim, bool useRound, uint digits)
  258. {
  259. int vCCount = values.Length % vDim;
  260. if (vDim < 2 | vDim > 3)
  261. throw new ArgumentException("Gm.SplitToVectors: vDim must be 2 or 3");
  262. if (vCCount > 0 & vCCount < vDim - 1)
  263. throw new ArgumentException("Gm.SplitToVectors: values");
  264. Vector[] ret = new Vector[(int)(values.Length / vDim) + (vCCount > 0 ? 1 : 0)];
  265. for (int i = 0, counter = 0; i < values.Length & counter < ret.Length; i += vDim, counter++)
  266. {
  267. if (vDim > 1)
  268. {
  269. ret[counter].x = values[i];
  270. ret[counter].y = values[i + 1];
  271. }
  272. if (vDim > 2 && i + 2 < values.Length)
  273. ret[counter].z = values[i + 2];
  274. // round
  275. if (useRound)
  276. ret[counter].Round(digits);
  277. }
  278. return ret;
  279. }
  280. /// <summary>
  281. /// Split double array to points
  282. /// </summary>
  283. /// <param name="values"></param>
  284. /// <param name="vDim"></param>
  285. /// <param name="useRound"></param>
  286. /// <param name="digits"></param>
  287. /// <returns></returns>
  288. public static Point[] SplitToPoints(double[] values, byte vDim, bool useRound, uint digits)
  289. {
  290. int vCCount = values.Length % vDim;
  291. if (vDim < 2 | vDim > 4)
  292. throw new ArgumentException("Gm.SplitToPoints: vDim must be 2 or 3");
  293. if (vCCount > 0 & vCCount < vDim - 1)
  294. throw new ArgumentException("Gm.SplitToPoints: values");
  295. Point[] ret = new Point[(int)(values.Length / vDim) + (vCCount > 0 ? 1 : 0)];
  296. for (int i = 0, counter = 0; i < values.Length & counter < ret.Length; i += vDim, counter++)
  297. {
  298. if (vDim > 1)
  299. {
  300. ret[counter].x = values[i];
  301. ret[counter].y = values[i + 1];
  302. }
  303. if (vDim > 2 && i + 2 < values.Length)
  304. ret[counter].z = values[i + 2];
  305. // uses round
  306. if (useRound)
  307. ret[counter].Round(digits);
  308. }
  309. return ret;
  310. }
  311. /// <summary>
  312. /// Split double array to points
  313. /// </summary>
  314. /// <param name="values"></param>
  315. /// <param name="vDim"></param>
  316. /// <param name="useRound"></param>
  317. /// <param name="digits"></param>
  318. /// <returns></returns>
  319. public static Point[] SplitToPoints(float[] values, byte vDim, bool useRound, uint digits)
  320. {
  321. int vCCount = values.Length % vDim;
  322. if (vDim < 2 | vDim > 4)
  323. throw new ArgumentException("Gm.SplitToPoints: vDim must be 2 or 3");
  324. if (vCCount > 0 & vCCount < vDim - 1)
  325. throw new ArgumentException("Gm.SplitToPoints: values");
  326. Point[] ret = new Point[(int)(values.Length / vDim) + (vCCount > 0 ? 1 : 0)];
  327. for (int i = 0, counter = 0; i < values.Length & counter < ret.Length; i += vDim, counter++)
  328. {
  329. if (vDim > 1)
  330. {
  331. ret[counter].x = values[i];
  332. ret[counter].y = values[i + 1];
  333. }
  334. if (vDim > 2 && i + 2 < values.Length)
  335. ret[counter].z = values[i + 2];
  336. // uses round
  337. if (useRound)
  338. ret[counter].Round(digits);
  339. }
  340. return ret;
  341. }
  342. public static double GetPolarAngle02P(double x, double y)
  343. {
  344. return Math.Atan(y / (x * x + y * y));
  345. }
  346. public static double iLeftOrRight(Point p, Point p1, Point p2)
  347. {
  348. double result = (p1.x - p.x) * (p2.y - p.y) - (p2.x - p.x) * (p1.y - p.y);
  349. if (Math.Abs(result) < Accuracy * Accuracy)
  350. result = 0;
  351. return result;
  352. }
  353. public static double SignTriangSquare(Point p1, Point p2, Point p3, bool isClockWice)
  354. {
  355. /*
  356. // p1, p2, p3
  357. -------
  358. x1 y1 1
  359. x2 y2 1
  360. x3 y3 1
  361. -------
  362. return m_matrix[0, 0] * m_matrix[1, 1] * m_matrix[2, 2] + m_matrix[0, 1] * m_matrix[1, 2] * m_matrix[2, 0] + m_matrix[0, 2] * m_matrix[1, 0] * m_matrix[2, 1]
  363. - m_matrix[0, 2] * m_matrix[1, 1] * m_matrix[2, 0] - m_matrix[0, 1] * m_matrix[1, 0] * m_matrix[2, 2] - m_matrix[0, 0] * m_matrix[1, 2] * m_matrix[2, 1];
  364. */
  365. double result = p1.x * p2.y + p1.y * p3.x + p2.x * p3.y - p2.y * p3.x - p1.y * p2.x - p1.x * p3.y;
  366. return isClockWice ? -result : result;
  367. }
  368. public static Point Mid(Point p1, Point p2)
  369. {
  370. double
  371. x = (p1.x + p2.x) / 2,
  372. y = (p1.y + p2.y) / 2,
  373. z = (p1.z + p2.z) / 2;
  374. return new Point(x, y, z);
  375. }
  376. public static bool DetectTriang(IEnumerable<Point> points,
  377. out Point p1, out Point p2, out Point p3)
  378. {
  379. ///Set points to default
  380. ///
  381. p1 = default(Point);
  382. p2 = default(Point);
  383. p3 = default(Point);
  384. /// Preparation
  385. ///
  386. IEnumerator<Point> iEnum = null;
  387. if (points == null)
  388. return false;
  389. if ((iEnum = points.GetEnumerator()) == null)
  390. return false;
  391. iEnum.Reset();
  392. ///Read first two points
  393. ///
  394. if (iEnum.MoveNext())
  395. p1 = iEnum.Current;
  396. else
  397. return false;
  398. if (iEnum.MoveNext())
  399. p2 = iEnum.Current;
  400. else
  401. return false;
  402. /// Search point
  403. ///
  404. while (iEnum.MoveNext())
  405. {
  406. if ( Math.Abs( iLeftOrRight(iEnum.Current, p1, p2)) > Accuracy)
  407. {
  408. p3 = iEnum.Current;
  409. return true;
  410. }
  411. }
  412. return false;
  413. }
  414. public static Point Centroid(IEnumerable<Point> points, out bool isDetect)
  415. {
  416. Point ret = default(Point),
  417. p1 = default(Point), p2 = default(Point), p3 = default(Point);
  418. isDetect = false;
  419. if (DetectTriang(points, out p1, out p2, out p3))
  420. {
  421. Point m1 = Mid(p2, p3);
  422. Point m2 = Mid(p1, p3);
  423. Point m3 = Mid(p1, p2);
  424. if (Intersect(p1, m1, p2, m2, out ret) < 1)
  425. {
  426. ret = default(Point);
  427. isDetect = false;
  428. }
  429. isDetect = true;
  430. }
  431. return ret;
  432. }
  433. public static void Sort(ref Point[] array, int minIndex, int maxIndex)
  434. {
  435. Dictionary<bool, List<Point>> convSegment = new Dictionary<bool, List<Point>>();
  436. /// up convex
  437. ///
  438. convSegment.Add(false, new List<Point>());
  439. /// down convex
  440. ///
  441. convSegment.Add(true, new List<Point>());
  442. for (int i = 0; i < array.Length; i++)
  443. {
  444. double res = Gm.iLeftOrRight(array[i], array[minIndex], array[maxIndex]);
  445. if (Math.Abs(res) < Accuracy)
  446. continue;
  447. if (res > 0)
  448. convSegment[false].Add(array[i]);
  449. else
  450. convSegment[true].Add(array[i]);
  451. }
  452. }
  453. public static bool Convex(ref Point[] tPoints)
  454. {
  455. int minIndex = 0, maxIndex = 0, tIndex = 0;
  456. double temp = 0;
  457. //double max = 0;
  458. //double min = 0;
  459. //if (tPoints.Length > 0)
  460. //{
  461. // min = tPoints[0].x;
  462. // max = tPoints[0].x;
  463. //}
  464. /// loock for min index and max index by x-componenta
  465. ///
  466. for (int i = 0; i < tPoints.Length; i++)
  467. {
  468. //if (min > tPoints[i].x)
  469. //{
  470. // min = tPoints[i].x;
  471. // minIndex = i;
  472. //}
  473. //if (max < tPoints[i].x)
  474. //{
  475. // max = tPoints[i].x;
  476. // maxIndex = i;
  477. //}
  478. System.Diagnostics.Debug.Print("x{0:F4}; y{1:F4}; z{2:F4};", new object[] { tPoints[i].x, tPoints[i].y, tPoints[i].z });
  479. if (tPoints[minIndex].x > tPoints[i].x)
  480. minIndex = i;
  481. if (tPoints[maxIndex].x < tPoints[i].x)
  482. maxIndex = i;
  483. }
  484. double tSquare = 0;
  485. /// Look for point with max triange square
  486. ///
  487. for (int i = 0; i < tPoints.Length; i++)
  488. {
  489. temp = Gm.TriangSquareGeron(tPoints[minIndex], tPoints[maxIndex], tPoints[i]);
  490. if (Math.Abs(tSquare)< Math.Abs(temp))
  491. {
  492. tSquare = temp;
  493. tIndex = i;
  494. }
  495. }
  496. bool isDetect = false;
  497. Point cPoint = Centroid(new Point[] { tPoints[minIndex], tPoints[maxIndex], tPoints[tIndex] }, out isDetect);
  498. /// projected face is line
  499. ///
  500. if (!isDetect)
  501. return false;
  502. /// projected face is polygon
  503. /// Sort points as polar angles
  504. ///
  505. Sort(ref tPoints, minIndex, maxIndex);
  506. return true;
  507. }
  508. public static void JoinConvex(ref List<Point> resultConvex, ref List<Point> convex1, ref List<Point> convex2)
  509. {
  510. }
  511. public static double Length2(Point p1, Point p2)
  512. {
  513. return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z);
  514. }
  515. public static double TriangSquareGeron(Point p1, Point p2, Point p3)
  516. {
  517. double a = Math.Sqrt(Length2(p1, p2));
  518. double b = Math.Sqrt(Length2(p2, p3));
  519. double c = Math.Sqrt(Length2(p1, p3));
  520. double p = 0.5 * (a + b + c);
  521. return p * Math.Sqrt((p - a) * (p - b) * (p - c));
  522. }
  523. public static double TriangSquare(Point p1, Point p2, Point p3)
  524. {
  525. return 0.5 * Math.Abs(SignTriangSquare(p1, p2, p3, false));
  526. }
  527. public static int Intersect(Point a1, Point a2, Point b1, Point b2, out Point intersection)
  528. {
  529. intersection = default(Point);
  530. double
  531. d = (a1.x - a2.x) * (b2.y - b1.y) - (a1.y - a2.y) * (b2.x - b1.x),
  532. da = (a1.x - b1.x) * (b2.y - b1.y) - (a1.y - b1.y) * (b2.x - b1.x),
  533. db = (a1.x - a2.x) * (a1.y - b1.y) - (a1.y - a2.y) * (a1.x - b1.x);
  534. if (Math.Abs(d) < Accuracy)
  535. return 0;
  536. double
  537. ta = da / d,
  538. tb = db / d;
  539. if (0 <= ta & ta <= 1 & 0 <= tb & tb <= 1)
  540. {
  541. intersection = new Point(a1.x + ta * (a2.x - a1.x), a1.y + ta * (a2.y - a1.y), 0);
  542. return 1;
  543. }
  544. return -1;
  545. }
  546. #endregion
  547. #region Vector definition
  548. //[System.Diagnostics.DebuggerDisplay("{format(4)}", Name = "Vector")]
  549. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  550. public struct Vector : INullable, IEquatable<Vector>
  551. {
  552. public double x;
  553. public double y;
  554. public double z;
  555. private bool m_null;
  556. private string format(byte dig)
  557. {
  558. Vector v = RoundTo(this,dig);
  559. return "(" + v.x.ToString() + "; " + v.y.ToString() + "; " + v.z.ToString() + "), Length:" + v.Length().ToString();
  560. }
  561. public Vector(double x, double y, double z)
  562. : this()
  563. {
  564. this.x = x;
  565. this.y = y;
  566. this.z = z;
  567. }
  568. public Vector(double[] points)
  569. : this()
  570. {
  571. if (points != null && points.Length >= 2)
  572. {
  573. this.x = points[0];
  574. this.y = points[1];
  575. if (points.Length > 2)
  576. this.z = points[2];
  577. }
  578. else
  579. throw new ArgumentOutOfRangeException("Array size have to be equal or greater than 3 elements");
  580. }
  581. public Vector(Vector v)
  582. : this()
  583. {
  584. this.x = v.x;
  585. this.y = v.y;
  586. this.z = v.z;
  587. }
  588. public void SetCoords(double x, double y, double z)
  589. {
  590. this.x = x;
  591. this.y = y;
  592. this.z = z;
  593. }
  594. public void SetCoords(Vector v)
  595. {
  596. this.x = v.x;
  597. this.y = v.y;
  598. this.z = v.z;
  599. }
  600. public void SetCoords(double[] points)
  601. {
  602. if (points != null && points.Length >= 2)
  603. {
  604. this.x = points[0];
  605. this.y = points[1];
  606. if (points.Length >= 3)
  607. this.z = points[2];
  608. }
  609. else
  610. throw new ArgumentOutOfRangeException("Array size have to be equal or greater than 3 elements");
  611. }
  612. public void Normalize()
  613. {
  614. double dist = Length2();
  615. if (dist > 0)
  616. {
  617. x /= dist;
  618. y /= dist;
  619. z /= dist;
  620. }
  621. }
  622. public Vector GetNormalized()
  623. {
  624. Vector v = new Vector(x, y, z);
  625. double dist = v.Length();
  626. if (dist > 0)
  627. {
  628. dist = 1 / dist;
  629. v.x *= dist;
  630. v.y *= dist;
  631. v.z *= dist;
  632. }
  633. return v;
  634. }
  635. /// <summary>
  636. /// Creates parallel vector, at point
  637. /// </summary>
  638. /// <param name="point"></param>
  639. /// <returns></returns>
  640. public Vector GetParallel(Point point)
  641. {
  642. Vector v = this;
  643. v.x += point.x;
  644. v.y += point.y;
  645. v.z += point.z;
  646. return v;
  647. }
  648. /// <summary>
  649. /// Creates parallel vector, at point
  650. /// </summary>
  651. /// <param name="point"></param>
  652. /// <returns></returns>
  653. public Vector GetParallel(double distance)
  654. {
  655. Vector normal = GetPerpVector()*distance;
  656. Vector v = normal.GetPerpVector();
  657. if (this.GetNormalized() != v)
  658. v.Inverce();
  659. return v;
  660. }
  661. /// <summary>
  662. /// Returns perpendicular vector
  663. /// </summary>
  664. /// <returns></returns>
  665. public Vector GetPerpVector()
  666. {
  667. if ((AngleTo(new Vector(0, 1, 0)) < Accuracy) || (AngleTo(new Vector(0, -1, 0)) < Accuracy))
  668. {
  669. return new Vector(y, 0, 0).GetNormalized();
  670. }
  671. return new Vector(z, 0, -x).GetNormalized();
  672. }
  673. public void Inverce() { x = -x; y = -y; z = -z; }
  674. /// <summary>
  675. /// Returns opposite vector
  676. /// </summary>
  677. /// <returns></returns>
  678. public Vector GetInverse()
  679. {
  680. return new Vector(-x, -y, -z);
  681. }
  682. public double Length()
  683. {
  684. return Math.Sqrt(x * x + y * y + z * z);
  685. }
  686. public double Length2()
  687. {
  688. return x * x + y * y + z * z;
  689. }
  690. public Vector Rotate(Vector dir, double ang)
  691. {
  692. if (ang == 0)
  693. return this;
  694. double c, s;
  695. double a;
  696. a = ang * Math.PI / 180;
  697. c = Math.Cos(a);
  698. s = Math.Sin(a);
  699. if (Double.IsNaN(c))
  700. c = 0;
  701. if (Double.IsNaN(s))
  702. s = 0;
  703. double nx, ny, nz;
  704. nx = x * (c + (1 - c) * (dir.x * dir.x)) + y * ((1 - c) * dir.y * dir.x + s * dir.z) + z * ((1 - c) * dir.z * dir.x - s * dir.y);
  705. ny = x * ((1 - c) * dir.y * dir.x - s * dir.z) + y * (c + (1 - c) * (dir.y * dir.y)) + z * ((1 - c) * dir.z * dir.y + s * dir.x);
  706. nz = x * ((1 - c) * dir.z * dir.x + s * dir.y) + y * ((1 - c) * dir.z * dir.y - s * dir.x) + z * (c + (1 - c) * (dir.z * dir.z));
  707. x = nx;
  708. y = ny;
  709. z = nz;
  710. return this;
  711. }
  712. public void Round(uint digits)
  713. {
  714. double factor1 = default(double);
  715. double factor2 = factor1;
  716. Factor(digits, out factor1, out factor2);
  717. if (Factor(digits, out factor1, out factor2))
  718. {
  719. x = (int)x;
  720. y = (int)y;
  721. z = (int)z;
  722. }
  723. else
  724. {
  725. x = ((int)(x * factor2)) * factor1;
  726. y = ((int)(y * factor2)) * factor1;
  727. z = ((int)(z * factor2)) * factor1;
  728. }
  729. }
  730. public double AngleTo(Vector vector)
  731. {
  732. if (vector.Length() == 0)
  733. return 0;
  734. double d = (this * vector) / (Length() * vector.Length());
  735. if (ApproximatelyEqual(d, 1, Accuracy))
  736. {
  737. d = 1;
  738. }
  739. else if (ApproximatelyEqual(d, -1, Accuracy))
  740. {
  741. d = -1;
  742. }
  743. return Math.Acos(d);
  744. }
  745. public double AngleToNonACos(Vector vector)
  746. {
  747. if (vector.Length() == 0)
  748. return 0;
  749. double d = (this * vector) / (Length() * vector.Length());
  750. if (ApproximatelyEqual(d, 1, Accuracy))
  751. {
  752. d = 1;
  753. }
  754. else if (ApproximatelyEqual(d, -1, Accuracy))
  755. {
  756. d = -1;
  757. }
  758. return d;
  759. }
  760. public bool IsParallelTo(Vector vector)
  761. {
  762. double angle = AngleTo(vector);
  763. return (ApproximatelyEqual(angle, 0, Accuracy) || ApproximatelyEqual(angle, Math.PI, Accuracy));
  764. }
  765. public bool IsPerpendicularTo(Vector vector)
  766. {
  767. return (ApproximatelyEqual(AngleTo(vector), Math.PI / 2));
  768. }
  769. /// <summary>
  770. /// Return rotated vector at transform data
  771. /// </summary>
  772. /// <param name="transform">transform matrix</param>
  773. /// <returns>rotated vector</returns>
  774. public Vector this[Transform transform]
  775. {
  776. get { return transform.TransformVector(this); }
  777. }
  778. #region INullable Members
  779. public bool IsNull { get { return m_null; } }//ApproximatelyEqual(x, 0) && ApproximatelyEqual(y, 0) && ApproximatelyEqual(z, 0);
  780. #endregion
  781. #region IEquatable<Vector> Members
  782. public override int GetHashCode()
  783. {
  784. return (int)Math.Sqrt(x * x * y * y * z * z);
  785. }
  786. public override bool Equals(object o)
  787. {
  788. if (o is Vector)
  789. {
  790. Vector v = (Vector)o;
  791. return !v.IsNull && Equals(v);
  792. }
  793. return false;
  794. }
  795. public bool Equals(Vector v)
  796. {
  797. return this == v;
  798. }
  799. public bool Equals(Vector vec, int tol)
  800. {
  801. return
  802. ApproximatelyEqual(vec.x, x, tol)
  803. &&
  804. ApproximatelyEqual(vec.y, y, tol)
  805. &&
  806. ApproximatelyEqual(vec.z, z, tol);
  807. }
  808. #endregion
  809. #region operators
  810. public static Vector operator +(Vector v1, Vector v2)
  811. {
  812. return new Vector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  813. }
  814. public static Vector operator -(Vector v1, Vector v2)
  815. {
  816. return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  817. }
  818. public static Vector operator *(Vector v1, double val)
  819. {
  820. return new Vector(v1.x * val, v1.y * val, v1.z * val);
  821. }
  822. public static Vector operator /(Vector v1, double val)
  823. {
  824. return new Vector(v1.x / val, v1.y / val, v1.z / val);
  825. }
  826. public static Vector operator ^(Vector v1, Vector v2)
  827. {
  828. #if L_ARM
  829. return new Vector(v2.y * v1.z - v2.z * v1.y, v2.z * v1.x - v2.x * v1.z, v2.x * v1.y - v2.y * v1.x);
  830. #else
  831. return new Vector(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x);
  832. #endif
  833. }
  834. public static double operator *(Vector v1, Vector v2)
  835. {
  836. return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  837. }
  838. public static bool operator ==(Vector v1, Vector v2)
  839. {
  840. return
  841. ApproximatelyEqual(v1.x, v2.x)
  842. &&
  843. ApproximatelyEqual(v1.y, v2.y)
  844. &&
  845. ApproximatelyEqual(v1.z, v2.z);
  846. }
  847. public static bool operator !=(Vector v1, Vector v2)
  848. {
  849. return !(v1 == v2);
  850. }
  851. public static implicit operator double[](Vector v1)
  852. {
  853. double[] arr = new double[3];
  854. arr[0] = v1.x;
  855. arr[1] = v1.y;
  856. arr[2] = v1.z;
  857. return arr;
  858. }
  859. public static implicit operator Vector(double[] points)
  860. {
  861. Vector v = new Vector();
  862. if (points != null && points.Length >= 2)
  863. {
  864. v.x = points[0];
  865. v.y = points[1];
  866. v.z = points[2];
  867. }
  868. else
  869. throw new ArgumentOutOfRangeException("Array size have to be equal or greater than 3 elements");
  870. return v;
  871. }
  872. #endregion
  873. #region static members
  874. public static Vector Null
  875. {
  876. get
  877. {
  878. Vector v = new Vector();
  879. v.m_null = true;
  880. return v;
  881. }
  882. }
  883. /// <summary>
  884. /// Calculate angle between vectors v1 and v2. All vectors mut be vectors with unit length
  885. /// </summary>
  886. /// <param name="axis">required to define sign of the angle</param>
  887. /// <param name="v1">first vector</param>
  888. /// <param name="v2">second vector</param>
  889. /// <returns>return signed angle value in radians</returns>
  890. public static double GetAngleZBetweenVectors(Vector axis, Vector v1, Vector v2)
  891. {
  892. Vector tmp = (v1 ^ v2);
  893. double cosAngle = v2 * v1;
  894. double angle = Math.Acos(cosAngle);
  895. if (Double.IsNaN(angle))
  896. angle = 0;
  897. if (tmp * axis < 0) //cos 90+ is negative
  898. angle = -angle;
  899. return angle;
  900. }
  901. #endregion
  902. }
  903. #endregion
  904. #region Point definition
  905. //[System.Diagnostics.DebuggerDisplay("{format(4)}", Name = "Point")]
  906. [Serializable]
  907. [DataContract]
  908. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  909. public struct Point : IEquatable<Point>, INullable, IBinarySerialize
  910. {
  911. [DataMember]
  912. public double x, y, z;
  913. private bool m_null;
  914. private string format(byte dig)
  915. {
  916. Point p = RoundTo(this, dig);
  917. return "(" + p.x.ToString() + "; " + p.y.ToString() + "; " + p.z.ToString() + ")";
  918. }
  919. public Point(double x, double y, double z)
  920. {
  921. m_null = false;
  922. this.x = x;
  923. this.y = y;
  924. this.z = z;
  925. }
  926. public Point(double x, double y) : this(x, y, 0) { }
  927. public void Translate(Vector vector)
  928. {
  929. x += vector.x;
  930. y += vector.y;
  931. z += vector.z;
  932. }
  933. public Point GetTranslated(Vector vector)
  934. {
  935. return this[vector];
  936. }
  937. public Point GetTransformed(Matrix3 matrix)
  938. {
  939. throw new NotImplementedException();
  940. }
  941. public void Transform(Matrix3 matrix)
  942. {
  943. throw new NotImplementedException();
  944. }
  945. public override int GetHashCode()
  946. {
  947. return base.GetHashCode();
  948. }
  949. public void Round(uint digits)
  950. {
  951. double factor1 = default(double);
  952. double factor2 = factor1;
  953. if (Factor(digits, out factor1, out factor2))
  954. {
  955. x = (int)x;
  956. y = (int)y;
  957. z = (int)z;
  958. }
  959. else
  960. {
  961. x = ((int)(x * factor2)) * factor1;
  962. y = ((int)(y * factor2)) * factor1;
  963. z = ((int)(z * factor2)) * factor1;
  964. }
  965. }
  966. public void MirrorAtOrigin()
  967. {
  968. x = -x;
  969. y = -y;
  970. z = -z;
  971. }
  972. public double DistanceTo(Point point)
  973. {
  974. return this[point].Length();
  975. }
  976. #region IEquatable<Point> Members
  977. public override bool Equals(object obj)
  978. {
  979. if (obj is Point)
  980. {
  981. var point = (Point)obj;
  982. if (this.x.Equals(point.x) && this.y.Equals(point.y) && this.z.Equals(point.z))
  983. return true;
  984. }
  985. return false;
  986. }
  987. public bool Equals(Point point)
  988. {
  989. return this == point;
  990. }
  991. #endregion
  992. public bool IsOrigin { get { return ApproximatelyEqual(x, 0) && ApproximatelyEqual(y, 0) && ApproximatelyEqual(z, 0); } }
  993. #region INullable Members
  994. public bool IsNull { get { return m_null; } }
  995. #endregion
  996. /// <summary>
  997. /// Returns non normailzed vector from this point and another
  998. /// </summary>
  999. /// <param name="end">Another point</param>
  1000. /// <returns></returns>
  1001. public Vector this[Point end]
  1002. {
  1003. get { return new Vector(end.x - x, end.y - y, end.z - z); }
  1004. }
  1005. /// <summary>
  1006. /// Returns point into new Transformation
  1007. /// </summary>
  1008. /// <param name="matrix">Transform matrix</param>
  1009. /// <returns></returns>
  1010. public Point this[Transform transform]
  1011. {
  1012. get
  1013. {
  1014. return transform.TransformPoint(this);
  1015. }
  1016. }
  1017. /// <summary>
  1018. /// Returns translated point at direction <paramref name="vactor"/>
  1019. /// </summary>
  1020. /// <param name="vector">translate direction</param>
  1021. /// <returns></returns>
  1022. public Point this[Vector vector] { get { return this + vector; } }
  1023. #region operators
  1024. public static bool operator ==(Point p1, object p2)
  1025. {
  1026. if (p2 == default(object))
  1027. return false;
  1028. return p1 == (Point)p2;
  1029. }
  1030. public static bool operator !=(Point p1, object p2)
  1031. {
  1032. if (p2 == default(object))
  1033. return true;
  1034. return p1 != (Point)p2;
  1035. }
  1036. public static bool operator ==(Point p1, Point p2)
  1037. {
  1038. return
  1039. Math.Abs(p1.x - p2.x) < Accuracy
  1040. &&
  1041. Math.Abs(p1.y - p2.y) < Accuracy
  1042. &&
  1043. Math.Abs(p1.z - p2.z) < Accuracy;
  1044. }
  1045. public static bool operator !=(Point p1, Point p2)
  1046. {
  1047. return !(p1 == p2);
  1048. }
  1049. public static Point operator +(Point point, Vector vector)
  1050. {
  1051. return new Point(point.x + vector.x, point.y + vector.y, point.z + vector.z);
  1052. }
  1053. public static Point operator -(Point point, Vector vector)
  1054. {
  1055. return new Point(point.x - vector.x, point.y - vector.y, point.z - vector.z);
  1056. }
  1057. public static Vector operator -(Point point1, Point point2)
  1058. {
  1059. return new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z);
  1060. }
  1061. public static Vector operator +(Point point1, Point point2)
  1062. {
  1063. return new Vector(point1.x + point2.x, point1.y + point2.y, point1.z + point2.z);
  1064. }
  1065. #endregion
  1066. #region static members
  1067. public static Point Null
  1068. {
  1069. get
  1070. {
  1071. Point p = new Point();
  1072. p.m_null = true;
  1073. return p;
  1074. }
  1075. }
  1076. #endregion
  1077. #region IBinarySerialize Members
  1078. public void Read(System.IO.BinaryReader r)
  1079. {
  1080. m_null = r.ReadBoolean();
  1081. x = r.ReadDouble();
  1082. y = r.ReadDouble();
  1083. z = r.ReadDouble();
  1084. }
  1085. public void Write(System.IO.BinaryWriter w)
  1086. {
  1087. w.Write(m_null);
  1088. w.Write(x);
  1089. w.Write(y);
  1090. w.Write(z);
  1091. }
  1092. #endregion
  1093. }
  1094. #endregion
  1095. #region Plane definition
  1096. //[System.Diagnostics.DebuggerDisplay("{format(4)}", Name = "Plane")]
  1097. [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
  1098. public struct Plane :INullable
  1099. {
  1100. private double[,] m_matr;
  1101. private bool m_null;
  1102. private string format(byte dig)
  1103. {
  1104. //Plane p = RoundTo(this, dig);
  1105. //"(" + p.x.ToString() + "; " + p.y.ToString() + "; " + p.z.ToString() + ")";
  1106. return string.Empty;
  1107. }
  1108. public Plane(Vector normal, Point point)
  1109. : this()
  1110. {
  1111. m_matr = new double[3, 3];
  1112. Vector perp1 = normal.GetPerpVector();
  1113. Vector perp2 = perp1 ^ normal;
  1114. Point p1 = point, p2 = point + perp1, p3 = point + perp2;
  1115. m_matr[0, 0] = p1.x;
  1116. m_matr[0, 1] = p1.y;
  1117. m_matr[0, 2] = p1.z;
  1118. m_matr[1, 0] = p2.x - p1.x;
  1119. m_matr[1, 1] = p2.y - p1.y;
  1120. m_matr[1, 2] = p2.z - p1.z;
  1121. m_matr[2, 0] = p3.x - p1.x;
  1122. m_matr[2, 1] = p3.y - p1.y;
  1123. m_matr[2, 2] = p3.z - p1.z;
  1124. }
  1125. public Plane(Point p1, Point p2, Point p3)
  1126. : this()
  1127. {
  1128. m_matr = new double[3, 3];
  1129. m_matr[0, 0] = p1.x;
  1130. m_matr[0, 1] = p1.y;
  1131. m_matr[0, 2] = p1.z;
  1132. m_matr[1, 0] = p2.x - p1.x;
  1133. m_matr[1, 1] = p2.y - p1.y;
  1134. m_matr[1, 2] = p2.z - p1.z;
  1135. m_matr[2, 0] = p3.x - p1.x;
  1136. m_matr[2, 1] = p3.y - p1.y;
  1137. m_matr[2, 2] = p3.z - p1.z;
  1138. }
  1139. public Plane(Vector v1, Vector v2, Point p): this()
  1140. {
  1141. m_matr = new double[3, 3];
  1142. Point p1 = p, p2 = p + v1, p3 = p + v2;
  1143. m_matr[0, 0] = p1.x;
  1144. m_matr[0, 1] = p1.y;
  1145. m_matr[0, 2] = p1.z;
  1146. m_matr[1, 0] = p2.x - p1.x;
  1147. m_matr[1, 1] = p2.y - p1.y;
  1148. m_matr[1, 2] = p2.z - p1.z;
  1149. m_matr[2, 0] = p3.x - p1.x;
  1150. m_matr[2, 1] = p3.y - p1.y;
  1151. m_matr[2, 2] = p3.z - p1.z;
  1152. }
  1153. public bool Contains(Vector vector)
  1154. {
  1155. return Contains(new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2])[vector]);
  1156. }
  1157. public bool Contains(Point point)
  1158. {
  1159. double a = point.x - m_matr[0, 0];
  1160. double b = point.y - m_matr[0, 1];
  1161. double c = point.z - m_matr[0, 2];
  1162. double det = a * m_matr[1, 1] * m_matr[2, 2];
  1163. det += b * m_matr[1, 2] * m_matr[2, 0];
  1164. det += c * m_matr[1, 0] * m_matr[2, 1];
  1165. det -= c * m_matr[1, 1] * m_matr[2, 0];
  1166. det -= b * m_matr[1, 0] * m_matr[2, 2];
  1167. det -= a * m_matr[1, 2] * m_matr[2, 1];
  1168. return ApproximatelyEqual(det, 0.0);
  1169. }
  1170. public double DistanceTo(Point point)
  1171. {
  1172. double[] x = new double[3];
  1173. double[] y = new double[3];
  1174. double[] z = new double[3];
  1175. for (int i = 0; i < 3; ++i)
  1176. {
  1177. x[i] = m_matr[i, 0];
  1178. y[i] = m_matr[i, 1];
  1179. z[i] = m_matr[i, 2];
  1180. }
  1181. double A = y[1] * z[2] - z[1] * y[2];
  1182. double B = x[2] * z[1] - x[1] * z[2];
  1183. double C = x[1] * y[2] - x[2] * y[1];
  1184. double D = x[0] * (z[1] * y[2] - y[1] * z[2]);
  1185. D += x[1] * (z[2] * y[0] - y[2] * z[0]);
  1186. D += x[2] * (y[1] * z[0] - z[1] * y[0]);
  1187. double retval = (A * point.x) + (B * point.y) + (C * point.z) + D;
  1188. retval /= Math.Sqrt((A * A) + (B * B) + (C * C));
  1189. return Math.Abs(retval);
  1190. }
  1191. public double DistanceTo(Plane plane)
  1192. {
  1193. return DistanceTo(new Point(plane.m_matr[0, 0], plane.m_matr[0, 1], m_matr[0, 2]));
  1194. }
  1195. public Point[] points
  1196. {
  1197. get
  1198. {
  1199. Point[] retval = new Point[3];
  1200. retval[0] = new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2]);
  1201. Vector vec = new Vector(m_matr[1, 0], m_matr[1, 1], m_matr[1, 2]);
  1202. retval[1] = retval[0] + vec;
  1203. vec = new Vector(m_matr[2, 0], m_matr[2, 1], m_matr[2, 2]);
  1204. retval[2] = retval[0] + vec;
  1205. return retval;
  1206. }
  1207. }
  1208. private Point intersect(Point a, Point b)
  1209. {
  1210. //sometimes (like in th bug #2307) we have very large inaccuracy
  1211. //so we need to square our angle to prevent the error
  1212. double angle = this.AngleTo(a[b]);
  1213. if (ApproximatelyEqual(Math.Pow(angle, 2), 0.0))
  1214. return Point.Null;
  1215. Point p = new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2]);
  1216. Vector l = new Vector(m_matr[1, 0], m_matr[1, 1], m_matr[1, 2]);
  1217. Vector m = new Vector(m_matr[2, 0], m_matr[2, 1], m_matr[2, 2]);
  1218. Vector val = l ^ m;
  1219. Point q = a + ((b - a) * (((p - a) * val) / ((b - a) * val)));
  1220. return q;
  1221. }
  1222. public Point[] Intersect(Plane plane)
  1223. {
  1224. Point[] ret = new Point[2];
  1225. Point[] pts = points;
  1226. List<Point[]> lines1 = new List<Point[]>();
  1227. lines1.Add(new Point[] { pts[0], pts[1]});
  1228. lines1.Add(new Point[] { pts[1], pts[2] });
  1229. lines1.Add(new Point[] { pts[2], pts[0] });
  1230. int k = 0;
  1231. for (int i = 0; i < lines1.Count; ++i)
  1232. if (!plane.IsParallel(lines1[i][1][lines1[i][0]]) && k != 2)
  1233. {
  1234. ret[k] = plane.intersect(lines1[i][0], lines1[i][1]);
  1235. k++;
  1236. }
  1237. if (k != 2)
  1238. return new Point[0];
  1239. return ret;
  1240. }
  1241. public Vector ParallelVector() { return (Normal ^ new Vector(0, 0, 1)).GetNormalized(); }
  1242. public Vector Normal
  1243. {
  1244. get
  1245. {
  1246. double[] x = new double[3];
  1247. double[] y = new double[3];
  1248. double[] z = new double[3];
  1249. for (int i = 0; i < 3; ++i)
  1250. {
  1251. x[i] = m_matr[i, 0];
  1252. y[i] = m_matr[i, 1];
  1253. z[i] = m_matr[i, 2];
  1254. }
  1255. double A = y[1] * z[2] - z[1] * y[2];
  1256. double B = x[2] * z[1] - x[1] * z[2];
  1257. double C = x[1] * y[2] - x[2] * y[1];
  1258. return (new Vector(A, B, C).GetNormalized());
  1259. }
  1260. }
  1261. public bool IsParallel(Plane p)
  1262. {
  1263. return Normal.IsParallelTo(p.Normal);
  1264. }
  1265. public bool IsParallel(Vector vector)
  1266. {
  1267. double angle = 0.0;
  1268. angle = Normal.AngleTo(vector);
  1269. return ApproximatelyEqual(angle, Math.PI) || ApproximatelyEqual(angle, 0) ;
  1270. }
  1271. public double AngleTo(Vector vector)
  1272. {
  1273. double angle = Normal.AngleTo(vector);
  1274. angle = (angle < (Math.PI / 2)) ? (Math.PI / 2 - angle) : angle - (Math.PI / 2);
  1275. return angle;
  1276. }
  1277. #region INullable Members
  1278. public bool IsNull { get { return m_null; } }
  1279. #endregion
  1280. #region Projection
  1281. public Point Projection(Point point)
  1282. {
  1283. double dist = DistanceTo(point);
  1284. Vector norm = Normal.GetNormalized();
  1285. Point pr = point - (norm * dist);
  1286. if (!ApproximatelyEqual(DistanceTo(pr), 0))
  1287. pr = point + (norm * dist);
  1288. return pr;
  1289. }
  1290. public Vector Projection(Vector vector)
  1291. {
  1292. Point p1 = new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2]);
  1293. Point p2 = Projection(p1[vector]);
  1294. return p1[p2];
  1295. }
  1296. #endregion
  1297. #region Shift
  1298. public void Shift(Vector direction)
  1299. {
  1300. Point
  1301. p1 = new Point(m_matr[0, 0], m_matr[0, 1], m_matr[0, 2]),
  1302. p2 = new Point(m_matr[1, 0] + p1.x, m_matr[1, 1] + p1.y, m_matr[1, 2] + p1.z),
  1303. p3 = new Point(m_matr[2, 0] + p1.x, m_matr[2, 1] + p1.y, m_matr[2, 2] + p1.z);
  1304. p1 = p1 + direction;
  1305. p2 = p2 + direction

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