Exemple #1
0
        static public List <Connector> GetConnectors(ConnectorManager conMngr)
        {
            List <Connector>     list = new List <Connector>();
            ConnectorSetIterator csi  = conMngr.Connectors.ForwardIterator();

            while (csi.MoveNext())
            {
                Connector conn = csi.Current as Connector;
                list.Add(conn);
            }
            return(list);
        }
Exemple #2
0
        // If originalConnector != null, use that connector for AddConnection routine, instead of connector.
        private static void ProcessConnections(ExporterIFC exporterIFC, Connector connector, Connector originalConnector)
        {
            Domain domain             = connector.Domain;
            bool   isElectricalDomain = (domain == Domain.DomainElectrical);
            bool   supportsDirection  = (domain == Domain.DomainHvac || domain == Domain.DomainPiping);

            ConnectorType connectorType = connector.ConnectorType;

            if (connectorType == ConnectorType.End ||
                connectorType == ConnectorType.Curve ||
                connectorType == ConnectorType.Physical)
            {
                if (connector.IsConnected)
                {
                    ConnectorSet         connectorSet = connector.AllRefs;
                    ConnectorSetIterator csi          = connectorSet.ForwardIterator();

                    while (csi.MoveNext())
                    {
                        Connector connected = csi.Current as Connector;
                        if (connected != null && connected.Owner != null && connector.Owner != null)
                        {
                            if (connected.Owner.Id != connector.Owner.Id)
                            {
                                // look for physical connections
                                ConnectorType connectedType = connected.ConnectorType;
                                if (connectedType == ConnectorType.End ||
                                    connectedType == ConnectorType.Curve ||
                                    connectedType == ConnectorType.Physical)
                                {
                                    Connector         originalConnectorToUse = (originalConnector != null) ? originalConnector : connector;
                                    FlowDirectionType flowDirection          = supportsDirection ? connector.Direction : FlowDirectionType.Bidirectional;
                                    if (flowDirection == FlowDirectionType.Out)
                                    {
                                        AddConnection(exporterIFC, connected, originalConnectorToUse, false, isElectricalDomain);
                                    }
                                    else
                                    {
                                        bool isBiDirectional = (flowDirection == FlowDirectionType.Bidirectional);
                                        AddConnection(exporterIFC, originalConnectorToUse, connected, isBiDirectional, isElectricalDomain);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// 获得某个元素的某个连接件上连接的其他元素
        /// </summary>
        /// <param name="element"></param>
        /// <param name="conn"></param>
        /// <returns></returns>
        public static List <Element> GetConnLinkedElements(Element element, Connector conn)
        {
            List <Element>       elements             = new List <Element>();
            ConnectorSetIterator connectorSetIterator = conn.AllRefs.ForwardIterator();

            while (connectorSetIterator.MoveNext())
            {
                Connector connref = connectorSetIterator.Current as Connector;
                Element   elem    = connref.Owner;
                if (elem != null && elem.UniqueId != element.UniqueId)
                {
                    elements.Add(elem);
                }
            }
            return(elements);
        }
Exemple #4
0
        /// <summary>
        /// 获取设备上指定点的连接键
        /// </summary>
        /// <param name="elem">设备</param>
        /// <param name="inspt">特定点</param>
        /// <returns>连接键</returns>
        public static Connector GetConnector(Element elem, XYZ inspt)
        {
            if (elem == null || inspt == null)
            {
                return(null);
            }
            ConnectorSet         cSet = GetConnectorSet(elem);
            ConnectorSetIterator csi  = cSet.ForwardIterator();

            while (csi.MoveNext())
            {
                Connector curConn = csi.Current as Connector;
                if (curConn.Origin.IsAlmostEqualTo(inspt))
                {
                    return(curConn);
                }
            }
            return(null);
        }
        // If originalConnector != null, use that connector for AddConnection routine, instead of connector.
        private static void ProcessConnections(ExporterIFC exporterIFC, Connector connector, Connector originalConnector)
        {
            // Port connection is not allowed for IFC4RV MVD
            if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView)
            {
                return;
            }

            Domain domain             = connector.Domain;
            bool   isElectricalDomain = (domain == Domain.DomainElectrical);
            bool   supportsDirection  = (domain == Domain.DomainHvac || domain == Domain.DomainPiping);

            ConnectorType connectorType = connector.ConnectorType;

            if (connectorType == ConnectorType.End ||
                connectorType == ConnectorType.Curve ||
                connectorType == ConnectorType.Physical)
            {
                Connector         originalConnectorToUse = (originalConnector != null) ? originalConnector : connector;
                FlowDirectionType flowDirection          = supportsDirection ? connector.Direction : FlowDirectionType.Bidirectional;
                bool isBiDirectional = (flowDirection == FlowDirectionType.Bidirectional);
                if (connector.IsConnected)
                {
                    ConnectorSet         connectorSet = connector.AllRefs;
                    ConnectorSetIterator csi          = connectorSet.ForwardIterator();

                    while (csi.MoveNext())
                    {
                        Connector connected = csi.Current as Connector;
                        if (connected != null && connected.Owner != null && connector.Owner != null)
                        {
                            if (connected.Owner.Id != connector.Owner.Id)
                            {
                                // look for physical connections
                                ConnectorType connectedType = connected.ConnectorType;
                                if (connectedType == ConnectorType.End ||
                                    connectedType == ConnectorType.Curve ||
                                    connectedType == ConnectorType.Physical)
                                {
                                    if (flowDirection == FlowDirectionType.Out)
                                    {
                                        AddConnection(exporterIFC, connected, originalConnectorToUse, false, isElectricalDomain);
                                    }
                                    else
                                    {
                                        AddConnection(exporterIFC, originalConnectorToUse, connected, isBiDirectional, isElectricalDomain);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    string           guid                 = GUIDUtil.CreateGUID();
                    IFCFlowDirection flowDir              = (isBiDirectional) ? IFCFlowDirection.SourceAndSink : (flowDirection == FlowDirectionType.Out ? IFCFlowDirection.Sink : IFCFlowDirection.Source);
                    Element          hostElement          = connector.Owner;
                    IFCAnyHandle     hostElementIFCHandle = ExporterCacheManager.MEPCache.Find(hostElement.Id);

                    if (ExporterCacheManager.ExportOptionsCache.ExportAs4 && !(IFCAnyHandleUtil.IsSubTypeOf(hostElementIFCHandle, IFCEntityType.IfcDistributionElement)))
                    {
                        return;
                    }

                    IFCAnyHandle localPlacement = CreateLocalPlacementForConnector(exporterIFC, connector, hostElementIFCHandle, flowDir);
                    IFCFile      ifcFile        = exporterIFC.GetFile();
                    IFCAnyHandle ownerHistory   = ExporterCacheManager.OwnerHistoryHandle;
                    IFCAnyHandle port           = IFCInstanceExporter.CreateDistributionPort(exporterIFC, null, guid, ownerHistory, localPlacement, null, flowDir);
                    string       portName       = "Port_" + hostElement.Id;
                    IFCAnyHandleUtil.OverrideNameAttribute(port, portName);
                    string portType = "Flow"; // Assigned as Port.Description
                    IFCAnyHandleUtil.SetAttribute(port, "Description", portType);

                    // Attach the port to the element
                    guid = GUIDUtil.CreateGUID();
                    string              connectionName  = hostElement.Id + "|" + guid;
                    IFCAnyHandle        connectorHandle = IFCInstanceExporter.CreateRelConnectsPortToElement(ifcFile, guid, ownerHistory, connectionName, portType, port, hostElementIFCHandle);
                    HashSet <MEPSystem> systemList      = new HashSet <MEPSystem>();
                    try
                    {
                        MEPSystem system = connector.MEPSystem;
                        if (system != null)
                        {
                            systemList.Add(system);
                        }
                    }
                    catch
                    {
                    }


                    if (isElectricalDomain)
                    {
                        foreach (MEPSystem system in systemList)
                        {
                            ExporterCacheManager.SystemsCache.AddElectricalSystem(system.Id);
                            ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, hostElementIFCHandle);
                            ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, port);
                        }
                    }
                    else
                    {
                        foreach (MEPSystem system in systemList)
                        {
                            ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, hostElementIFCHandle);
                            ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, port);
                        }
                    }
                }
            }
        }
        // If originalConnector != null, use that connector for AddConnection routine, instead of connector.
        private static void ProcessConnections(ExporterIFC exporterIFC, Connector connector, Connector originalConnector)
        {
            // Port connection is not allowed for IFC4RV MVD
            bool isIFC4AndAbove = !ExporterCacheManager.ExportOptionsCache.ExportAsOlderThanIFC4;

            Domain domain             = connector.Domain;
            bool   isElectricalDomain = (domain == Domain.DomainElectrical);
            bool   supportsDirection  = (domain == Domain.DomainHvac || domain == Domain.DomainPiping);

            ConnectorType connectorType = connector.ConnectorType;

            if (connectorType == ConnectorType.End ||
                connectorType == ConnectorType.Curve ||
                connectorType == ConnectorType.Physical)
            {
                Connector         originalConnectorToUse = originalConnector ?? connector;
                FlowDirectionType flowDirection          = supportsDirection ? connector.Direction : FlowDirectionType.Bidirectional;
                bool isBiDirectional = (flowDirection == FlowDirectionType.Bidirectional);
                if (connector.IsConnected)
                {
                    ConnectorSet         connectorSet = connector.AllRefs;
                    ConnectorSetIterator csi          = connectorSet.ForwardIterator();

                    while (csi.MoveNext())
                    {
                        Connector connected = csi.Current as Connector;
                        if (connected != null && connected.Owner != null && connector.Owner != null)
                        {
                            if (connected.Owner.Id != connector.Owner.Id)
                            {
                                // look for physical connections
                                ConnectorType connectedType = connected.ConnectorType;
                                if (connectedType == ConnectorType.End ||
                                    connectedType == ConnectorType.Curve ||
                                    connectedType == ConnectorType.Physical)
                                {
                                    if (flowDirection == FlowDirectionType.Out)
                                    {
                                        AddConnection(exporterIFC, connected, originalConnectorToUse, false, isElectricalDomain);
                                    }
                                    else
                                    {
                                        AddConnection(exporterIFC, originalConnectorToUse, connected, isBiDirectional, isElectricalDomain);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    Element hostElement = connector.Owner;

                    IFCFlowDirection flowDir = (isBiDirectional) ? IFCFlowDirection.SourceAndSink : (flowDirection == FlowDirectionType.Out ? IFCFlowDirection.Source : IFCFlowDirection.Sink);
                    IFCAnyHandle     hostElementIFCHandle = ExporterCacheManager.MEPCache.Find(hostElement.Id);
                    string           guid = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcDistributionPort,
                                                                         connector.Id.ToString(), hostElementIFCHandle);

                    IFCAnyHandle localPlacement = CreateLocalPlacementForConnector(exporterIFC, connector, hostElementIFCHandle, flowDir);
                    IFCFile      ifcFile        = exporterIFC.GetFile();
                    IFCAnyHandle ownerHistory   = ExporterCacheManager.OwnerHistoryHandle;
                    IFCAnyHandle port           = IFCInstanceExporter.CreateDistributionPort(exporterIFC, null, guid,
                                                                                             ownerHistory, localPlacement, null, flowDir);
                    string portType = "Flow"; // Assigned as Port.Description
                    ExporterCacheManager.MEPCache.CacheConnectorHandle(connector, port);
                    SetDistributionPortAttributes(port, connector, portType, hostElement.Id, ref flowDir);

                    // Port connection is changed in IFC4 to use IfcRelNests for static connection. IfcRelConnectsPortToElement is used for a dynamic connection and it is restricted to IfcDistributionElement
                    // The following code collects the ports that are nested to the object to be assigned later
                    if (isIFC4AndAbove)
                    {
                        AddNestedMembership(hostElementIFCHandle, port);
                    }
                    else
                    {
                        // Attach the port to the element
                        string relGuid        = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcRelConnectsPortToElement, connector.Id.ToString(), port);
                        string connectionName = hostElement.Id + "|" + guid;
                        IFCInstanceExporter.CreateRelConnectsPortToElement(ifcFile, relGuid, ownerHistory, connectionName, portType, port, hostElementIFCHandle);
                    }

                    HashSet <MEPSystem> systemList = new HashSet <MEPSystem>();
                    try
                    {
                        MEPSystem system = connector.MEPSystem;
                        if (system != null)
                        {
                            systemList.Add(system);
                        }
                    }
                    catch
                    {
                    }

                    if (isElectricalDomain)
                    {
                        foreach (MEPSystem system in systemList)
                        {
                            ExporterCacheManager.SystemsCache.AddElectricalSystem(system.Id);
                            ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, hostElementIFCHandle);
                            ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, port);
                        }
                    }
                    else
                    {
                        foreach (MEPSystem system in systemList)
                        {
                            ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, hostElementIFCHandle);
                            ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, port);
                        }
                    }
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Exports a connector instance. Almost verbatim exmaple from Revit 2012 API for Connector Class
        /// Works only for HVAC and Piping for now
        /// </summary>
        /// <param name="exporterIFC">The ExporterIFC object.</param>
        /// <param name="connectors">The ConnectorSet object.</param>
        private static void Export(ExporterIFC exporterIFC, ConnectorSet connectors)
        {
            IFCFile file = exporterIFC.GetFile();

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                foreach (Connector connector in connectors)
                {
                    try
                    {
                        if (connector != null)
                        {
                            if (connector.Domain == Domain.DomainHvac || connector.Domain == Domain.DomainPiping)
                            {
                                if (connector.ConnectorType == ConnectorType.End ||
                                    connector.ConnectorType == ConnectorType.Curve ||
                                    connector.ConnectorType == ConnectorType.Physical)
                                {
                                    if (connector.IsConnected)
                                    {
                                        ConnectorSet         connectorSet = connector.AllRefs;
                                        ConnectorSetIterator csi          = connectorSet.ForwardIterator();

                                        while (csi.MoveNext())
                                        {
                                            Connector connected = csi.Current as Connector;
                                            if (connected != null && connected.Owner != null && connector.Owner != null)
                                            {
                                                if (connected.Owner.Id != connector.Owner.Id)
                                                {
                                                    // look for physical connections
                                                    if (connected.ConnectorType == ConnectorType.End ||
                                                        connected.ConnectorType == ConnectorType.Curve ||
                                                        connected.ConnectorType == ConnectorType.Physical)
                                                    {
                                                        if (connector.Direction == FlowDirectionType.Out)
                                                        {
                                                            AddConnection(file, exporterIFC, connected.Owner, connector.Owner, false);
                                                        }
                                                        else
                                                        {
                                                            bool isBiDirectional = (connector.Direction == FlowDirectionType.Bidirectional);
                                                            AddConnection(file, exporterIFC, connector.Owner, connected.Owner, isBiDirectional);
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch (System.Exception)
                    {
                        // Log an error here
                    }
                }
                tr.Commit();
            }
        }
        public Result Run()
        {
            Trace.Listeners.Clear();
            Trace.AutoFlush = true;
            string outputFileName = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "AutoRoute.log");

            if (File.Exists(outputFileName))
            {
                File.Delete(outputFileName);
            }
            TextWriterTraceListener listener = new TextWriterTraceListener(outputFileName);

            Trace.Listeners.Add(listener);

            //
            ElementClassFilter       systemTypeFilter = new ElementClassFilter(typeof(MEPSystemType));
            FilteredElementCollector C = new FilteredElementCollector(m_document);

            C.WherePasses(systemTypeFilter);
            foreach (MEPSystemType type in C)
            {
                if (type.SystemClassification == MEPSystemClassification.SupplyAir)
                {
                    m_systemTypeId = type.Id; //送风系统
                    break;
                }
            }

            Transaction transaction = new Transaction(m_document, "Sample_AutoRoute");

            try
            {
                transaction.Start();

                //标高
                m_level = Level.Create(m_document, 0.0);

                //Element
                List <Autodesk.Revit.DB.ElementId> ids = new List <ElementId>();
                ids.Add(new ElementId(730127)); //baseEquipment
                ids.Add(new ElementId(730237));
                ids.Add(new ElementId(730244));

                //Init Elements Info
                FamilyInstance[] instances = new FamilyInstance[3];
                BoundingBoxXYZ[] boxes     = new BoundingBoxXYZ[3];
                Connector[]      conns     = new Connector[3];

                ConnectorSetIterator csi = null;
                for (int i = 0; i < ids.Count; i++)
                {
                    Element element = m_document.GetElement(ids[i]);
                    if (null == element)
                    {
                        return(Result.Failed);
                    }

                    instances[i] = element as FamilyInstance;
                    csi          = ConnectorInfo.GetConnectors(element).ForwardIterator();
                    csi.MoveNext();
                    conns[i] = csi.Current as Connector;
                    boxes[i] = instances[i].get_BoundingBox(m_document.ActiveView);
                }

                //Find the "Out" and "SupplyAir" connector on the base equipment
                //the first element is base equipment
                var baseEquipment = instances[0];
                csi = ConnectorInfo.GetConnectors(baseEquipment).ForwardIterator();
                while (csi.MoveNext())
                {
                    Connector conn = csi.Current as Connector;
                    if (conn.Domain == Domain.DomainHvac ||
                        conn.Domain == Domain.DomainPiping)
                    {
                        //conn.Direction 只有DomainHvac和DomainPiping有
                        if (conn.Direction == FlowDirectionType.Out)
                        {
                            DuctSystemType ductSystemType = DuctSystemType.UndefinedSystemType;
                            try
                            {
                                //DuctSystemType PipeSystemType ElectricalSystemType
                                //每个连接件只有上述三个中的一个,调用其他时回报异常
                                ductSystemType = conn.DuctSystemType;
                            }
                            catch { continue; }
                            if (ductSystemType == DuctSystemType.SupplyAir)
                            {
                                conns[0] = conn;
                                break;
                            }
                        }
                    }
                }

                //mechanicalSystem
                m_mechanicalSystem = CreateMechanicalSystem(
                    //[378728][SupplyAir][Out][RectProfile][OST_MechanicalEquipment]
                    new ConnectorInfo(baseEquipment, conns[0].Origin.X, conns[0].Origin.Y, conns[0].Origin.Z),
                    new ConnectorInfo[] {
                    //[378707][SupplyAir][In][RectProfile]
                    new ConnectorInfo(instances[1], conns[1].Origin.X, conns[1].Origin.Y, conns[1].Origin.Z),
                    //[378716][SupplyAir][In][RectProfile]
                    new ConnectorInfo(instances[2], conns[2].Origin.X, conns[2].Origin.Y, conns[2].Origin.Z)
                },
                    DuctSystemType.SupplyAir
                    );

                //Get the boundary of the system
                double minX = conns[0].Origin.X;
                double minY = conns[0].Origin.Y;
                double maxX = conns[0].Origin.X;
                double maxY = conns[0].Origin.Y;
                double maxZ = conns[0].Origin.Z;
                for (int i = 1; i < boxes.Length; ++i)
                {
                    if (conns[i].Origin.X < minX)
                    {
                        minX = conns[i].Origin.X;
                    }
                    if (conns[i].Origin.Y < minY)
                    {
                        minY = conns[i].Origin.Y;
                    }
                    if (conns[i].Origin.X > maxX)
                    {
                        maxX = conns[i].Origin.X;
                    }
                    if (conns[i].Origin.Y > maxY)
                    {
                        maxY = conns[i].Origin.Y;
                    }
                    if (conns[i].Origin.Z > maxZ)
                    {
                        maxZ = conns[i].Origin.Z;
                    }
                }

                //Calculate the optional values(可选值) for the trunk ducts
                double   midX        = (minX + maxX) / 2;
                double   midY        = (minY + maxY) / 2;
                double[] baseXValues = new double[3] {
                    midX, (minX + midX) / 2, (maxX + midX) / 2
                };
                double[] baseYValues = new double[3] {
                    midY, (minY + midY) / 2, (maxY + midY) / 2
                };

                //ductType
                m_ductType = m_document.GetElement(m_ductTypeId) as DuctType;

                List <XYZ> points = new List <XYZ>();

                //conn[0]相关点
                #region conn[0]
                XYZ connectorDirection = conns[0].CoordinateSystem.BasisZ;
                if (0 == connectorDirection.DistanceTo(new XYZ(-1, 0, 0)))
                {
                    points.Add(new XYZ(conns[0].Origin.X - min1FittingLength, conns[0].Origin.Y, conns[0].Origin.Z));
                    points.Add(new XYZ(conns[0].Origin.X - min2FittingsLength, conns[0].Origin.Y, conns[0].Origin.Z + min1FittingLength));
                    points.Add(new XYZ(conns[0].Origin.X - min2FittingsLength, conns[0].Origin.Y, maxZ + verticalTrunkOffset - min1FittingLength));
                }
                else if (0 == connectorDirection.DistanceTo(new XYZ(1, 0, 0)))
                {
                    points.Add(new XYZ(conns[0].Origin.X + min1FittingLength, conns[0].Origin.Y, conns[0].Origin.Z));
                    points.Add(new XYZ(conns[0].Origin.X + min2FittingsLength, conns[0].Origin.Y, conns[0].Origin.Z + min1FittingLength));
                    points.Add(new XYZ(conns[0].Origin.X + min2FittingsLength, conns[0].Origin.Y, maxZ + verticalTrunkOffset - min1FittingLength));
                }
                else if (0 == connectorDirection.DistanceTo(new XYZ(0, -1, 0)))
                {
                    points.Add(new XYZ(conns[0].Origin.X, conns[0].Origin.Y - min1FittingLength, conns[0].Origin.Z));
                    points.Add(new XYZ(conns[0].Origin.X, conns[0].Origin.Y - min2FittingsLength, conns[0].Origin.Z + min1FittingLength));
                    points.Add(new XYZ(conns[0].Origin.X, conns[0].Origin.Y - min2FittingsLength, maxZ + verticalTrunkOffset - min1FittingLength));
                }
                else if (0 == connectorDirection.DistanceTo(new XYZ(0, 1, 0)))
                {
                    points.Add(new XYZ(conns[0].Origin.X, conns[0].Origin.Y + min1FittingLength, conns[0].Origin.Z));
                    points.Add(new XYZ(conns[0].Origin.X, conns[0].Origin.Y + min2FittingsLength, conns[0].Origin.Z + min1FittingLength));
                    points.Add(new XYZ(conns[0].Origin.X, conns[0].Origin.Y + min2FittingsLength, maxZ + verticalTrunkOffset - min1FittingLength));
                }
                #endregion

                //开始创建风管
                List <Duct>      ducts          = new List <Duct>();
                List <Connector> connectors     = new List <Connector>();
                List <Connector> baseConnectors = new List <Connector>();

                ducts.Add(Duct.Create(m_document, m_ductTypeId, m_level.Id, conns[0], points[0]));
                ducts.Add(Duct.Create(m_document, m_systemTypeId, m_ductTypeId, m_level.Id, points[1], points[2]));

                connectors.Add(ConnectorInfo.GetConnector(ducts[0], points[0]));
                connectors.Add(ConnectorInfo.GetConnector(ducts[1], points[1]));
                connectors.Add(ConnectorInfo.GetConnector(ducts[1], points[2]));

                //连接管道,二选一,效果是一样的
                //connectors[0].ConnectTo(connectors[1]);
                m_document.Create.NewElbowFitting(connectors[0], connectors[1]);

                baseConnectors.Add(connectors[2]);

                //Create the vertical ducts for terminals
                points.Clear();
                ducts.Clear();

                //conn[1] conn[2] 相关点
                points.Add(new XYZ(conns[1].Origin.X, conns[1].Origin.Y, maxZ + verticalTrunkOffset - min1FittingLength));
                points.Add(new XYZ(conns[2].Origin.X, conns[2].Origin.Y, maxZ + verticalTrunkOffset - min1FittingLength));

                ducts.Add(Duct.Create(m_document, m_ductTypeId, m_level.Id, conns[1], points[0]));
                ducts.Add(Duct.Create(m_document, m_ductTypeId, m_level.Id, conns[2], points[1]));
                baseConnectors.Add(ConnectorInfo.GetConnector(ducts[0], points[0]));
                baseConnectors.Add(ConnectorInfo.GetConnector(ducts[1], points[1]));


                ////最顶部的 baseConnectors 相关
                //SortConnectorsByX(baseConnectors);
                //for (int i = 0; i < baseYValues.Length; ++i)
                //{
                //    if (ConnectSystemOnXAxis(baseConnectors, baseYValues[i]))
                //    {
                //        LogUtility.WriteMechanicalSystem(m_mechanicalSystem);
                //        return Autodesk.Revit.UI.Result.Succeeded;
                //    }
                //}

                SortConnectorsByY(baseConnectors);
                for (int i = 0; i < baseXValues.Length; ++i)
                {
                    if (ConnectSystemOnYAxis(baseConnectors, baseXValues[i]))
                    {
                        LogUtility.WriteMechanicalSystem(m_mechanicalSystem);

                        transaction.Commit();
                        return(Autodesk.Revit.UI.Result.Succeeded);
                    }
                }


                ////如果任然无法连接,把干管放到maxbbox外
                //SortConnectorsByX(baseConnectors);
                //if (ConnectSystemOnXAxis(baseConnectors, maxY + horizontalOptionalTrunkOffset))
                //{
                //    LogUtility.WriteMechanicalSystem(m_mechanicalSystem);
                //    return Autodesk.Revit.UI.Result.Succeeded;
                //}

                //SortConnectorsByY(baseConnectors);
                //if (ConnectSystemOnYAxis(baseConnectors, maxX + horizontalOptionalTrunkOffset))
                //{
                //    LogUtility.WriteMechanicalSystem(m_mechanicalSystem);
                //    return Autodesk.Revit.UI.Result.Succeeded;
                //}


                ////如果任然无法连接,随便连一个,让revit报错吧
                //connectors.Clear();
                //SortConnectorsByX(baseConnectors);
                //connectors.AddRange(CreateDuct(new XYZ(baseConnectors[0].Origin.X + min1FittingLength, baseYValues[0], maxZ + verticalTrunkOffset), new XYZ(baseConnectors[1].Origin.X - min1FittingLength, baseYValues[0], maxZ + verticalTrunkOffset)));
                //connectors.AddRange(CreateDuct(new XYZ(baseConnectors[1].Origin.X + min1FittingLength, baseYValues[0], maxZ + verticalTrunkOffset), new XYZ(baseConnectors[2].Origin.X - min1FittingLength, baseYValues[0], maxZ + verticalTrunkOffset)));
                //ConnectWithElbowFittingOnXAxis(baseConnectors[0], connectors[0]);
                //ConnectWithElbowFittingOnXAxis(baseConnectors[2], connectors[3]);
                //ConnectWithTeeFittingOnXAxis(baseConnectors[1], connectors[1], connectors[2], false);
            }
            catch (Exception ex)
            {
                transaction.RollBack();
                Trace.WriteLine(ex.ToString());
                return(Autodesk.Revit.UI.Result.Failed);
            }
            finally
            {
                Trace.Flush();
                listener.Close();
                Trace.Close();
                Trace.Listeners.Remove(listener);
            }

            transaction.RollBack();
            return(Result.Succeeded);
        }