自动管线翻弯

    using Autodesk.Revit.Attributes;
    using Autodesk.Revit.DB;
    using Autodesk.Revit.DB.Electrical;
    using Autodesk.Revit.DB.Mechanical;
    using Autodesk.Revit.DB.Plumbing;
    using Autodesk.Revit.UI;
    using Autodesk.Revit.UI.Selection;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace 管线翻弯避让
    {
        [Transaction(TransactionMode.Manual)]
        public class Class1 : IExternalCommand
        {
            public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
            {
                UIDocument uidoc = commandData.Application.ActiveUIDocument;
                Document doc = uidoc.Document;
                //预设集合,后续用于关键删除
                List<ElementId> elementsToDel = new List<ElementId>();
                //选择风管
                Reference rfDuct = uidoc.Selection.PickObject(ObjectType.Element, "选择风管");
                //获取风管及其定位线
                Duct duct = doc.GetElement(rfDuct) as Duct;
                Line ductLine = (duct.Location as LocationCurve).Curve as Line;
                //收集所有管道
                FilteredElementCollector pipeCol = new FilteredElementCollector(doc);
                pipeCol.OfClass(typeof(Pipe));
                //获取与风管相交的管线
                ElementIntersectsElementFilter filter = new ElementIntersectsElementFilter(duct);
                IList<Element> intersectPipes = pipeCol.WherePasses(filter).ToElements();
                //新建并启动事务
                Transaction transaction = new Transaction(doc, "管线翻弯避让");
                transaction.Start();
                foreach (Element element in intersectPipes)
                {
                    Pipe pipe = element as Pipe;
                    List<Pipe> newPipes = new List<Pipe>();
                    //获取管道的尺寸
                    double d = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble();
                    //获取管道的系统类型
                    ElementId sTypeId = pipe.MEPSystem.GetTypeId();
                    PipingSystemType systype = doc.GetElement(sTypeId) as PipingSystemType;
                    //获取管道类型
                    PipeType pType = doc.GetElement(pipe.GetTypeId()) as PipeType;
                    ElementId pTypeId = pType.Id;
                    //获取管道标高
                    ElementId levelid = pipe.ReferenceLevel.Id;
                    //获得管道定位线
                    Line pipeLine = (pipe.Location as LocationCurve).Curve as Line;
                    XYZ pStart = pipeLine.GetEndPoint(0);
                    XYZ pEnd = pipeLine.GetEndPoint(1);
                    //获得管道起终点的连接件
                    Connector conStart = ConnectorAtPoint(pipe, pStart);
                    Connector conEnd = ConnectorAtPoint(pipe, pEnd);
                    //获取与管道起终点相连的关键的连接件(可能为null)
                    Connector fittingConStart = GetConToConctor(conStart);
                    Connector fittingConEnd = GetConToConctor(conEnd);
                    //线取消原管道两端的连接,以便新管道与之连接
                    if (fittingConStart!=null)
                    {
                        conStart.DisconnectFrom(fittingConStart);
                    }
                    if (fittingConEnd!=null)
                    {
                        conEnd.DisconnectFrom(fittingConEnd);
                    }
                    //将原管道存入待删除集合
                    elementsToDel.Add(pipe.Id);
                    //关键步骤一:获得风管和管线交点
                    XYZ intersectPoint = GetIntersectPoint(pipeLine, ductLine);
                    if (intersectPoint == null)
                        continue;
                    //关键步骤二:获得翻弯后6个管道控制点,一次存入集合 
                    List<XYZ> points = GetPipePoints(pipeLine, duct, d, intersectPoint);

                    //关键步骤三:依次生成5个新管道
                    for (int i = 0; i < points.Count-1; i++)
                    {
                        Pipe newPipe = Pipe.Create(doc, sTypeId, pTypeId, levelid, points[i],points[i+1]);
                        //设置新管道尺寸
                        newPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(d);
                        //把新管道添加到集合中
                        newPipes.Add(newPipe);
                    }
                    //关键步骤四:连接新生成的管道
                    CreateConnector(doc, points, newPipes);
                    //关键步骤五:恢复原两端连接
                    //获得新管道线在原两端点出的Connector
                    Connector newConStart = ConnectorAtPoint(newPipes.First(), pStart);
                    Connector newConEnd = ConnectorAtPoint(newPipes.Last(), pEnd);
                    //恢复与原关键的连接
                    if (fittingConStart!=null)
                        newConStart.ConnectTo(fittingConStart);
                    if (fittingConEnd != null)
                        newConEnd.ConnectTo(fittingConEnd);
                }
                //删除原管道
                doc.Delete(elementsToDel);
                //提交事务
                transaction.Commit();
                return Result.Succeeded;
            }

            public Connector ConnectorAtPoint(Element e, XYZ point)
            {
                ConnectorSet connectorSet = null;
                //风管连接件集合
                if (e is Duct)
                    connectorSet = (e as Duct).ConnectorManager.Connectors;
                //管线连接件集合
                if (e is Pipe)
                    connectorSet = (e as Pipe).ConnectorManager.Connectors;
                //桥架的连接件集合
                if (e is CableTray)
                    connectorSet = (e as CableTray).ConnectorManager.Connectors;
                //管件等可载入族的连接件集合
                if (e is FamilyInstance)
                {
                    FamilyInstance fi = e as FamilyInstance;
                    connectorSet = fi.MEPModel.ConnectorManager.Connectors;
                }
                //遍历连接件集合
                foreach (Connector connector in connectorSet)
                {
                    //如果连接件的中心和目标点相距很小时视为目标连接件
                    if (connector.Origin.DistanceTo(point) < 1 / 304.8)
                        //返回该连接件
                        return connector;
                }
                //如果没有匹配到,则返回null
                return null;
            }
            //获取与管线相连的管件连接件
            public Connector GetConToConctor(Connector connector)
            {
                foreach (Connector con in connector.AllRefs)
                {
                    //仅选择管件
                    if (con.Owner is FamilyInstance)
                    {
                        return con;
                    }
                }
                return null;
            }
            /// <summary>
            /// 关键步骤一:获取风管与管道的交点
            /// </summary>
            /// <param name="pLine">管道定位线</param>
            /// <param name="dLine">风管定位线</param>
            /// <returns></returns>
            private XYZ GetIntersectPoint(Line pLine, Line dLine)
            {
                XYZ intersectPoint = null;
                //获取风管和管线的定位线的端点
                XYZ ductStart = dLine.GetEndPoint(0);
                XYZ ductEnd = dLine.GetEndPoint(1);
                XYZ pipeStart = pLine.GetEndPoint(0);
                //把风管定位线投影到与管线定位线统一平面上
                ductStart = new XYZ(ductStart.X, ductStart.Y, pipeStart.Z);
                ductEnd = new XYZ(ductEnd.X, ductEnd.Y, pipeStart.Z);
                dLine = Line.CreateBound(ductStart, ductEnd);
                //找到交点
                IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
                SetComparisonResult result = dLine.Intersect(pLine, out intersectionResultArray);
                if (result != SetComparisonResult.Disjoint)
                {
                    intersectPoint = intersectionResultArray.get_Item(0).XYZPoint;
                }
                //返回交点
                return intersectPoint;
            }
            //关键步骤2:获得翻弯后管道控制点
            private List<XYZ> GetPipePoints(Line line, Duct duct, double d, XYZ point)
            {
                //记录控制点集
                List<XYZ> pipePoints = new List<XYZ>();
                //收集风管的宽度和高度,案例只考虑矩形分管,为考虑保温层
                double dh, dw;
                dw = duct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).AsDouble();
                dh = duct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).AsDouble();
                //得到管线的方向
                XYZ pipeDir = line.Direction;
                //得到管线端点在水平方向上移动的距离
                double horDou = dw / 2 + d + 100 / 304.8;
                //得到管线端点在竖直方向上移动的距离
                double verDou = dh / 2 + d + 100 / 304.8;
                //得到新平行管线的定位线的定位点
                XYZ p1 = line.GetEndPoint(0);
                XYZ p2 = point.Add(-pipeDir * horDou);
                XYZ p3 = new XYZ(p2.X, p2.Y, p2.Z + verDou);
                XYZ p6 = line.GetEndPoint(1);
                XYZ p5 = point.Add(pipeDir * horDou);
                XYZ p4 = new XYZ(p5.X, p5.Y, p5.Z + verDou);
                //添加到集合中
                pipePoints.Add(p1);
                pipePoints.Add(p2);
                pipePoints.Add(p3);
                pipePoints.Add(p4);
                pipePoints.Add(p5);
                pipePoints.Add(p6);
                return pipePoints;
            }
            //连接管线
            private void CreateConnector(Document doc, List<XYZ> points, List<Pipe> pipes)
            {
                for (int i = 0; i < pipes.Count - 1; i++)
                {
                    //获得匹配的连接件
                    Connector con1 = ConnectorAtPoint(pipes[i], points[i + 1]);
                    Connector con2 = ConnectorAtPoint(pipes[i + 1], points[i + 1]);

                    //创建弯头
                    doc.Create.NewElbowFitting(con1, con2);
                }
            }


        }
    }

上一篇:tomcat基于NIO、NIO2、APR的http链接器支持的属性


下一篇:mybatis 代码生成器