using System; using System.Collections.Generic; using System.Linq; using System.Text; using WinForm = System.Windows.Forms; using Autodesk.Revit.UI; using Autodesk.Revit.DB; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.UI.Selection; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.DB.ExtensibleStorage; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.DB.Architecture; using System.Xml; using SelSet = HongYe.Revit.Public.SelectSet; using Autodesk.Revit.DB.Electrical; using System.Diagnostics; using System.Security.Cryptography; using System.IO; namespace RevitCodes { /// <summary> /// 工具类 /// </summary> public class RevitTool { /// <summary> /// 管件是否连接风管,如果什么也没连接也返回true /// </summary> /// <returns></returns> public static bool IsConnectToDuct(FamilyInstance fi) { bool bResult = true; ConnectorSetIterator csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator(); while (csi.MoveNext()) { Connector conn = csi.Current as Connector; if (conn.IsConnected == true) // 是否有连接 { ConnectorSet connectorSet = conn.AllRefs; // 找到所有连接器连接的连接器 ConnectorSetIterator csiChild = connectorSet.ForwardIterator(); while (csiChild.MoveNext()) { Connector connected = csiChild.Current as Connector; if ( null != connected && connected.Owner.UniqueId != conn.Owner.UniqueId) { // TaskDialog.Show("conn", conn.Width + "|" + connected.Width + ","); // look for physical connections if (connected.ConnectorType == ConnectorType.End || connected.ConnectorType == ConnectorType.Curve || connected.ConnectorType == ConnectorType.Physical) { // 判断是不是管件,只要有一头连接的不是风管就返回false if (connected.Owner is Duct) { Duct duct = connected.Owner as Duct; Parameter pWidth = duct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM); Parameter pHeight = duct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM); // TaskDialog.Show("width", pWidth.AsValueString()); } else { bResult = false; break; } } } } } } return bResult; } /// <summary> /// 改变风管尺寸 /// </summary> /// <param name="duct"></param> /// <param name="sWidth"></param> /// <param name="sHeight"></param> public static void ChangeDuctSize(Duct duct, string sWidth, string sHeight) { Parameter pWidth = duct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM); Parameter pHeight = duct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM); pWidth.SetValueString(sWidth); pHeight.SetValueString(sHeight); } /// <summary> /// 改变管件尺寸 /// </summary> /// <param name="fi"></param> /// <param name="dWidth"></param> /// <param name="dHeight"></param> public static void ChangeFittingSize(FamilyInstance fi, double dWidth, double dHeight) { ConnectorSetIterator csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator(); while (csi.MoveNext()) { Connector conn = csi.Current as Connector; conn.Width = dWidth / 304.8; conn.Height = dHeight / 304.8; } } /// <summary> /// 是否需要变换 /// </summary> /// <param name="fi"></param> /// <returns></returns> public static bool isChange(FamilyInstance fi) { bool bChange = true; // 是否需要变换宽高 XYZ xyzFace = GetFittingSolid(fi).Normal; // 正面朝上或者朝下,不需要变换 if (xyzFace.AngleTo( new XYZ( 0, 0, 1)) < 0.001 || xyzFace.AngleTo( new XYZ( 0, 0, - 1)) < 0.001) { bChange = false; } return bChange; } /// <summary> /// 取得管件的几何体的方向面,管件族的几何体,有三个。 /// </summary> /// <param name="fi"></param> /// <returns></returns> public static PlanarFace GetFittingSolid(FamilyInstance fi) { // 得到管件尺寸 double dWidth = 0, dHeight = 0; ConnectorSetIterator csi = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator(); while (csi.MoveNext()) { Connector conn = csi.Current as Connector; dWidth = conn.Width; dHeight = conn.Height; } // PlanarFace resultFace = null; Solid resultSolid = null; // Options opt = new Options(); opt.ComputeReferences = true; opt.DetailLevel = Autodesk.Revit.DB.DetailLevels.Medium; // GeometryElement e = fi.get_Geometry(opt); foreach (GeometryObject obj in e.Objects) { GeometryInstance gi = obj as GeometryInstance; if (gi != null) { GeometryElement ge = gi.GetInstanceGeometry(); foreach (GeometryObject go in ge.Objects) { Solid solid = go as Solid; if (solid != null && solid.Faces.Size > 0) { bool isSolid = true; foreach (Face face in solid.Faces) { PlanarFace pf = face as PlanarFace; if (pf != null) { if (pf.Area < 0.02) // 如果有一个面积特别小,这个截面体。角度为1度也大于0.02 { isSolid = false; } } } if (isSolid) { resultSolid = solid; } } } } } // 找到截面 double dArea = dWidth * dHeight; PlanarFace sectionFace = null; foreach (Face face in resultSolid.Faces) { if (Math.Abs(face.Area - dArea) < 0.001) // 面积近似 { sectionFace = face as PlanarFace; break; } } // 找到与截面垂直的管件正面 foreach (Face face in resultSolid.Faces) { PlanarFace pFace = face as PlanarFace; if (pFace != null) { // 面积相同的排除 if (Math.Abs(face.Area - dArea) < 0.001) // 面积近似 { continue; } else { double dAngle = pFace.Normal.AngleTo(sectionFace.Normal); if (Math.Abs(dAngle - Math.PI / 2) < 0.001) // 与截面垂直的面 { resultFace = pFace; } } } } // return resultFace; } /// <summary> /// 从框选元素中过滤出风管 /// </summary> /// <param name="listElement"></param> /// <returns></returns> public static List<Duct> GetDuctsFromElements(IList<Element> listElement) { List<Duct> listDuct = new List<Duct>(); foreach (Element el in listElement) { if (el is Duct) { Duct duct = el as Duct; listDuct.Add(duct); } } return listDuct; } /// <summary> /// 从框选元素中过滤出管件 /// </summary> /// <param name="listElement"></param> /// <returns></returns> public static List<FamilyInstance> GetFittingsFromElements(IList<Element> listElement) { List<FamilyInstance> listFitting = new List<FamilyInstance>(); foreach (Element el in listElement) { if (el is FamilyInstance) { FamilyInstance fi = el as FamilyInstance; listFitting.Add(fi); } } return listFitting; } } // 改变尺寸方法一 [TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)] public class cmdChangeSize1 : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string messages, ElementSet elements) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; Selection sel = app.ActiveUIDocument.Selection; Transaction ts = new Transaction(doc, " hongye "); // double dWidth = 800; double dHeight = 400; IList<Element> listElement = sel.PickElementsByRectangle( " 框选一个弯头及相连的两根风管 "); List<Duct> listDuct = RevitTool.GetDuctsFromElements(listElement); List<FamilyInstance> listFi = RevitTool.GetFittingsFromElements(listElement); // 第一步,改变管件尺寸,改变后,肯定会增加变径。 ts.Start(); foreach (FamilyInstance fi in listFi) { RevitTool.ChangeFittingSize(fi, dWidth, dHeight); } ts.Commit(); // 第二步,改变风管尺寸,如果不需要变换,变径会自动消失。 ts.Start(); foreach (Duct duct in listDuct) { RevitTool.ChangeDuctSize(duct, dWidth.ToString(), dHeight.ToString()); } ts.Commit(); // 第三步,判断风管与管件之间是否仍然存在变径,如果存在则宽度互换,再次改变风管尺寸。 ts.Start(); foreach (FamilyInstance fi in listFi) { if (!RevitTool.IsConnectToDuct(fi)) // 如果连接的是变径 { foreach (Duct duct in listDuct) { RevitTool.ChangeDuctSize(duct, dHeight.ToString(), dWidth.ToString()); } } } ts.Commit(); // pf.Normal.AngleTo return Result.Succeeded; } } // 改变尺寸方法二 [TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)] public class cmdChangeSize2 : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string messages, ElementSet elements) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; Selection sel = app.ActiveUIDocument.Selection; Transaction ts = new Transaction(doc, " hongye "); ts.Start(); // double dWidth = 800; double dHeight = 400; IList<Element> listElement = sel.PickElementsByRectangle( " 框选一个弯头及相连的两根风管 "); List<Duct> listDuct = RevitTool.GetDuctsFromElements(listElement); List<FamilyInstance> listFi = RevitTool.GetFittingsFromElements(listElement); // foreach (FamilyInstance fi in listFi) { RevitTool.ChangeFittingSize(fi, dWidth, dHeight); if (RevitTool.isChange(fi)) { foreach (Duct duct in listDuct) { RevitTool.ChangeDuctSize(duct, dHeight.ToString(), dWidth.ToString()); } } else { foreach (Duct duct in listDuct) { RevitTool.ChangeDuctSize(duct, dWidth.ToString(), dHeight.ToString()); } } } ts.Commit(); return Result.Succeeded; } } }