XYZExtension.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using Autodesk.Revit.DB;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using FWindSoft.SystemExtensions;
  8. namespace FWindSoft.Revit
  9. {
  10. /// <summary>
  11. /// 点的扩展相关
  12. /// </summary>
  13. public static class XYZExtension
  14. {
  15. /// <summary>
  16. /// 向量是否平行
  17. /// </summary>
  18. /// <param name="baseDirection"></param>
  19. /// <param name="direction"></param>
  20. /// <returns></returns>
  21. public static bool IsParallel(this XYZ baseDirection, XYZ direction)
  22. {
  23. return baseDirection.CrossProduct(direction).GetLength().IsZero();
  24. }
  25. /// <summary>
  26. /// 向量是否垂直
  27. /// </summary>
  28. /// <param name="baseDirection"></param>
  29. /// <param name="direction"></param>
  30. /// <returns></returns>
  31. public static bool IsVertical(this XYZ baseDirection, XYZ direction)
  32. {
  33. return baseDirection.DotProduct(direction).IsZero();
  34. }
  35. /// <summary>
  36. /// 判断向量是否同向
  37. /// </summary>
  38. /// <param name="firstDirection"></param>
  39. /// <param name="secondDirection"></param>
  40. /// <returns></returns>
  41. public static bool IsSameDirection(this XYZ firstDirection, XYZ secondDirection)
  42. {
  43. if(firstDirection.IsParallel(secondDirection))
  44. {
  45. return firstDirection.DotProduct(secondDirection).MoreEqual(0);
  46. }
  47. return false;
  48. }
  49. /// <summary>
  50. /// 向量方向相反
  51. /// </summary>
  52. /// <param name="firstDirection"></param>
  53. /// <param name="secondDirection"></param>
  54. /// <returns></returns>
  55. public static bool IsOppositeDirection(this XYZ firstDirection, XYZ secondDirection)
  56. {
  57. if (firstDirection.IsParallel(secondDirection))
  58. {
  59. return secondDirection.DotProduct(secondDirection).LessEqual(0);
  60. }
  61. return false;
  62. }
  63. /// <summary>
  64. /// 偏移指定向量
  65. /// </summary>
  66. /// <param name="origin"></param>
  67. /// <param name="vector"></param>
  68. /// <returns></returns>
  69. public static XYZ Offset(this XYZ origin,XYZ vector)
  70. {
  71. return origin + vector;
  72. }
  73. /// <summary>
  74. /// 判断两个点是否重合
  75. /// </summary>
  76. /// <param name="first"></param>
  77. /// <param name="second"></param>
  78. /// <param name="tolerance"></param>
  79. /// <returns></returns>
  80. public static bool IsEqual(this XYZ first, XYZ second, double tolerance)
  81. {
  82. return first.X.IsEqual(second.X, tolerance)
  83. && first.Y.IsEqual(second.Y, tolerance)
  84. && first.Z.IsEqual(second.Z, tolerance);
  85. }
  86. /// <summary>
  87. /// 判断两个点是否重合
  88. /// </summary>
  89. /// <param name="first"></param>
  90. /// <param name="second"></param>
  91. /// <returns></returns>
  92. public static bool IsEqual(this XYZ first, XYZ second)
  93. {
  94. return first.X.IsEqual(second.X, DoubleExtensions.Precision)
  95. && first.Y.IsEqual(second.Y, DoubleExtensions.Precision)
  96. && first.Z.IsEqual(second.Z, DoubleExtensions.Precision);
  97. }
  98. /// <summary>
  99. /// 判断两个点是否重合
  100. /// </summary>
  101. /// <param name="first"></param>
  102. /// <param name="second"></param>
  103. /// <returns></returns>
  104. public static bool IsEqual2(this XYZ first, XYZ second)
  105. {
  106. return first.X.IsEqual(second.X, DoubleExtensions.Precision)
  107. && first.Y.IsEqual(second.Y, DoubleExtensions.Precision);
  108. }
  109. /// <summary>
  110. /// 按指定方向的轴,在原点位置旋转向量
  111. /// </summary>
  112. /// <param name="vec"></param>
  113. /// <param name="axis"></param>
  114. /// <param name="angle"></param>
  115. /// <returns></returns>
  116. public static XYZ RotateVector(this XYZ vec, XYZ axis, double angle)
  117. {
  118. var transform = Transform.CreateRotationAtPoint(axis, angle, XYZ.Zero);
  119. return transform.OfVector(vec);
  120. }
  121. /// <summary>
  122. /// 计算点到指定平面的投影
  123. /// </summary>
  124. /// <param name="input"></param>
  125. /// <param name="normal"></param>
  126. /// <param name="origin"></param>
  127. /// <returns></returns>
  128. public static XYZ GetPlaneProject(this XYZ input, XYZ normal, XYZ origin)
  129. {
  130. if (!normal.IsUnitLength())
  131. {
  132. normal = normal.Normalize();
  133. }
  134. return input + normal * origin.Subtract(input).DotProduct(normal);
  135. }
  136. /// <summary>
  137. /// 计算点到指定直线的投影
  138. /// </summary>
  139. /// <param name="input"></param>
  140. /// <param name="direction"></param>
  141. /// <param name="origin"></param>
  142. /// <returns></returns>
  143. public static XYZ GetLineProject(this XYZ input, XYZ direction, XYZ origin)
  144. {
  145. if (!direction.IsUnitLength())
  146. {
  147. direction = direction.Normalize();
  148. }
  149. return origin + direction * input.Subtract(origin).DotProduct(direction);
  150. }
  151. /// <summary>
  152. /// 获取任意一个与input垂直的向量
  153. /// </summary>
  154. /// <param name="input"></param>
  155. /// <returns></returns>
  156. public static XYZ GetAnyVerticalVector(this XYZ input)
  157. {
  158. if (!XYZ.BasisX.IsParallel(input))
  159. {
  160. return input.CrossProduct(XYZ.BasisX).Normalize();
  161. }
  162. else
  163. {
  164. return input.CrossProduct(XYZ.BasisY).Normalize();
  165. }
  166. }
  167. /// <summary>
  168. /// 判断点的投影是否在直线段内
  169. /// </summary>
  170. /// <param name="input"></param>
  171. /// <param name="line"></param>
  172. /// <returns></returns>
  173. public static bool IsProjectInLine(this XYZ input, Line line)
  174. {
  175. if (!line.IsBound)
  176. {
  177. return true;
  178. }
  179. var project =line.GetProject(input);
  180. return line.InCurve(project);
  181. }
  182. /// <summary>
  183. /// 使用Input在line上的投影点分割指定直线
  184. /// </summary>
  185. /// <param name="input"></param>
  186. /// <param name="line"></param>
  187. /// <returns>如果点在线外侧,则返回一个较大的向量,另一个去掉。如果在线上,则返回两个向量</returns>
  188. public static List<XYZ> SplitVector(this XYZ input, Line line)
  189. {
  190. if (!line.IsBound)
  191. {
  192. return new List<XYZ>() { line.Direction * Double.MaxValue, line.Direction * Double.MaxValue, };
  193. }
  194. var project = line.GetProject(input);
  195. var startVector = line.StartPoint() - project;
  196. var endVector = line.EndPoint() - project;
  197. if (startVector.DotProduct(endVector).MoreEqual(0))
  198. {
  199. //两个向量同向,去较大的返回
  200. if (startVector.GetLength().More(endVector.GetLength()))
  201. {
  202. return new List<XYZ>() { startVector };
  203. }
  204. else
  205. {
  206. return new List<XYZ>() { endVector };
  207. }
  208. }
  209. return new List<XYZ>() { startVector, endVector };
  210. }
  211. }
  212. }