GetEdgesCmd.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Autodesk.Revit;
  7. using Autodesk.Revit.DB;
  8. using Autodesk.Revit.UI;
  9. using Autodesk.Revit.DB.Mechanical;
  10. using System.Windows;
  11. using System.Windows.Shapes;
  12. using System.Windows.Media;
  13. using System.Windows.Controls;
  14. namespace SpacePlugin
  15. {
  16. [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
  17. [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
  18. [Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)]
  19. public class GetEdgesCmd : IExternalCommand
  20. {
  21. /// <summary>
  22. /// Implement this method as an external command for Revit.
  23. /// </summary>
  24. /// <param name="commandData">An object that is passed to the external application
  25. /// which contains data related to the command,
  26. /// such as the application object and active view.</param>
  27. /// <param name="message">A message that can be set by the external application
  28. /// which will be displayed if a failure or cancellation is returned by
  29. /// the external command.</param>
  30. /// <param name="elements">A set of elements to which the external application
  31. /// can add elements that are to be highlighted in case of failure or cancellation.</param>
  32. /// <returns>Return the status of the external command.
  33. /// A result of Succeeded means that the API external method functioned as expected.
  34. /// Cancelled can be used to signify that the user cancelled the external operation
  35. /// at some point. Failure should be returned if the application is unable to proceed with
  36. /// the operation.</returns>
  37. public Result Execute(ExternalCommandData commandData,
  38. ref string message,
  39. ElementSet elements)
  40. {
  41. try
  42. {
  43. Transaction docTrans = new Transaction(commandData.Application.ActiveUIDocument.Document, "Document");
  44. docTrans.Start();
  45. UIApplication uiApp = commandData.Application;
  46. UIDocument uiDoc = commandData.Application.ActiveUIDocument;
  47. Document doc = uiDoc.Document;
  48. ElementClassFilter familyInstanceFilter = new ElementClassFilter(typeof(FamilyInstance));
  49. var lstCategoryFilter = new List<ElementFilter>
  50. {
  51. new ElementCategoryFilter(BuiltInCategory.OST_Doors),
  52. new ElementCategoryFilter(BuiltInCategory.OST_Windows),
  53. new ElementCategoryFilter(BuiltInCategory.OST_StructuralColumns)
  54. };
  55. LogicalOrFilter orCategoryFilter = new LogicalOrFilter(lstCategoryFilter);
  56. LogicalAndFilter andFilter = new LogicalAndFilter(familyInstanceFilter, orCategoryFilter);
  57. ElementClassFilter wallFilter = new ElementClassFilter(typeof(Wall));
  58. LogicalOrFilter filter = new LogicalOrFilter(andFilter, wallFilter);
  59. FilteredElementCollector collector = new FilteredElementCollector(doc);
  60. var lstEle = collector.WherePasses(filter).ToList();
  61. if (lstEle.Count == 0)
  62. {
  63. MessageBox.Show("没发现可生成空间的元素");
  64. docTrans.RollBack();
  65. return Result.Failed;
  66. }
  67. WinSpaceBottom win = new WinSpaceBottom();
  68. foreach (var ele in lstEle)
  69. {
  70. var brush = (ele is Wall) ? green : red;
  71. var curve = ele.Location as LocationCurve;
  72. if (curve == null)
  73. {
  74. this.DrawBottomFace(ele, win.canvas);
  75. }
  76. else
  77. {
  78. this.DrawCurve(curve.Curve, win.canvas, brush);
  79. }
  80. }
  81. var width = (maxX - minX) * 1.2;
  82. var height = (maxY - minY) * 1.2;
  83. foreach (UIElement ele in win.canvas.Children)
  84. {
  85. Canvas.SetLeft(ele, -minX + width * 0.1);
  86. Canvas.SetTop(ele, -minY + height * 0.1);
  87. }
  88. win.canvas.Width = width;
  89. win.canvas.Height = height;
  90. win.Show();
  91. docTrans.Commit();
  92. return Result.Succeeded;
  93. }
  94. catch (Exception exp)
  95. {
  96. message = exp.Message;
  97. return Result.Failed;
  98. }
  99. }
  100. SolidColorBrush green = new SolidColorBrush(Colors.Green);
  101. SolidColorBrush red = new SolidColorBrush(Colors.Red);
  102. double minX = double.MaxValue;
  103. double maxX = 0.0;
  104. double minY = double.MaxValue;
  105. double maxY = 0.0;
  106. const double Scale = 50.0;
  107. void DrawBottomFace(Element ele, Canvas canvas)
  108. {
  109. Options opt = new Options();
  110. opt.ComputeReferences = true;
  111. opt.DetailLevel = ViewDetailLevel.Medium;
  112. GeometryElement e = ele.get_Geometry(opt);
  113. foreach (GeometryObject obj in e)
  114. {
  115. if (obj is Solid)
  116. {
  117. Solid solid = obj as Solid;
  118. if (solid != null && solid.Faces.Size > 0) this.DrawSolid(solid, canvas, green);
  119. }
  120. else if (obj is GeometryInstance)
  121. {
  122. var sube = (obj as GeometryInstance).GetInstanceGeometry();
  123. foreach (GeometryObject subobj in sube)
  124. {
  125. Solid subsolid = subobj as Solid;
  126. if (subsolid != null && subsolid.Faces.Size > 0) this.DrawSolid(subsolid, canvas, red);
  127. }
  128. }
  129. }
  130. }
  131. void DrawSolid(Solid solid, Canvas canvas, Brush brush)
  132. {
  133. var pf = FindBottomFace(solid);
  134. if (pf == null) return;
  135. foreach (EdgeArray edgeArr in pf.EdgeLoops)
  136. {
  137. var pl = this.CreateDefaultPolyLine(brush);
  138. foreach (Edge edge in edgeArr)
  139. {
  140. var lstPt = edge.Tessellate().ToList();
  141. this.AddPoints(lstPt, pl);
  142. }
  143. canvas.Children.Add(pl);
  144. }
  145. }
  146. PlanarFace FindBottomFace(Solid solid)
  147. {
  148. PlanarFace pf = null;
  149. foreach (Face face in solid.Faces)
  150. {
  151. pf = face as PlanarFace;//转化为立面平面
  152. if (pf == null) continue;
  153. var normal = pf.FaceNormal;
  154. if (Math.Abs(normal.X) < 0.01 && Math.Abs(normal.Y) < 0.01 && normal.Z < 0)
  155. break;
  156. }
  157. return pf;
  158. }
  159. void DrawCurve(Curve curve, Canvas canvas, Brush brush)
  160. {
  161. var lstPt = curve.Tessellate();
  162. if (lstPt == null || lstPt.Count < 2) return;
  163. var pl = this.CreateDefaultPolyLine(brush);
  164. this.AddPoints(lstPt, pl);
  165. canvas.Children.Add(pl);
  166. }
  167. void AddPoints(IEnumerable<XYZ> lstPt, Polyline pl)
  168. {
  169. foreach (var pt in lstPt)
  170. {
  171. var x = pt.X * Scale;
  172. //由于winform,y轴与revit Y轴方向相反。Winform Y向下
  173. var y = pt.Y * Scale*(-1);
  174. if (x < minX) minX = x;
  175. if (x > maxX) maxX = x;
  176. if (y < minY) minY = y;
  177. if (y > maxY) maxY = y;
  178. pl.Points.Add(new System.Windows.Point(x, y));
  179. }
  180. }
  181. Polyline CreateDefaultPolyLine(Brush brush)
  182. {
  183. var pl = new Polyline();
  184. pl.Stroke = brush;
  185. pl.StrokeThickness = 2;
  186. pl.StrokeStartLineCap = PenLineCap.Flat;
  187. pl.StrokeEndLineCap = PenLineCap.Flat;
  188. pl.StrokeLineJoin = PenLineJoin.Round;
  189. return pl;
  190. }
  191. }
  192. }