Ejemplo n.º 1
0
        public static Duct MakeDuct(Document doc, XYZ p1, XYZ p2, ElementId typ, ElementId mst, object diameter, object insulationThick)
        {
            if (typ == null)
            {
                throw new ArgumentNullException("A Duct Type must be specified");
            }



            // use default level (actually - it appears that this doesn't work???
            ElementId     level       = new ElementId(-1);
            IList <Level> levelsBelow = getAllLevelsBelow(doc, Math.Min(p1.Z, p2.Z));
            Level         levElement  = null;

            if (levelsBelow != null)
            {
                levElement = levelsBelow[0];
            }
            else
            {
                levElement = getClosestLevel(doc, Math.Min(p1.Z, p2.Z));
            }
            Duct d = Duct.Create(doc, mst, typ, levElement.Id, p1, p2);

            if (diameter != null)
            {
                if (diameter is String)
                {
                    d.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).SetValueString(diameter.ToString());
                }
                if (diameter is double)
                {
                    d.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).Set(Convert.ToDouble(diameter));
                }
            }
            if (insulationThick != null)
            {
                //if (insulationThick is String)
                //{
                //    d.get_Parameter(BuiltInParameter.RBS_PIPE_INSULATION_THICKNESS).SetValueString(insulationThick.ToString());
                //}
                //if (insulationThick is double)
                //{
                //    double ins = Convert.ToDouble(insulationThick);
                //    if (ins != 0) d.get_Parameter(BuiltInParameter.RBS_PIPE_INSULATION_THICKNESS).Set(Convert.ToDouble(insulationThick));
                //}
                double thick = Convert.ToDouble(insulationThick);
                if (thick > 0)
                {
                    DuctInsulation test = DuctInsulation.Create(doc, d.Id, new ElementId(-1), Convert.ToDouble(insulationThick));
                }
            }


            return(d);
        }
Ejemplo n.º 2
0
        private List <Connector> CreateDuct(XYZ point1, XYZ point2)
        {
            List <Connector> connectors = new List <Connector>();

            Duct duct = Duct.Create(m_document, m_systemTypeId, m_ductTypeId, m_level.Id, point1, point2);

            connectors.Add(ConnectorInfo.GetConnector(duct, point1));
            connectors.Add(ConnectorInfo.GetConnector(duct, point2));

            return(connectors);
        }
Ejemplo n.º 3
0
        private void CreateDucts(int jndex)
        {
            if (sortedlocalsTech.ElementAt(jndex).ElementAt(0).Name.Contains("GT24"))
            {
                Debug.WriteLine("TEST GAINE 24");
            }
            Debug.WriteLine(jndex);
            ElementId levelId = ElementId.InvalidElementId;

            tiltingSpaces.Clear();
            GetBestPath();
            GetTiltingSpace();
            GetBestPosition();
            currentConn = null;

            for (int i = 0; i < sortedlocalsTech.ElementAt(jndex).Count();)
            {
                if (sortedlocalsTech.ElementAt(jndex).Count() == 1)
                {
                    Debug.WriteLine("i: " + i);
                    break;
                }

                Element e     = doc.GetElement(sortedlocalsTech.ElementAt(jndex).ElementAt(i).Id);
                var     space = doc.GetElement(sortedlocalsTech.ElementAt(jndex).ElementAt(i).Id) as Space;

                try
                {
                    if (i >= RevitDataContext.lazyInstance.SpacesInfo.Count())
                    {
                        break;
                    }
                    SpatialElementGeometryCalculator calculator = new SpatialElementGeometryCalculator(doc);
                    SpatialElementGeometryResults    results    = calculator.CalculateSpatialElementGeometry(space); // compute the room geometry
                    Solid       roomSolid = results.GetGeometry();
                    List <Face> lf        = new List <Face>();
                    List <XYZ>  Edges     = new List <XYZ>();
                    List <XYZ>  temp      = new List <XYZ>();
                    foreach (Face face in roomSolid.Faces)
                    {
                        foreach (EdgeArray item in face.EdgeLoops)
                        {
                            List <XYZ> lc = JtBoundingBoxXyzExtensionMethods.GetPolygon(item);
                            foreach (var subitem in lc)
                            {
                                temp.Add(subitem);
                            }
                        }
                    }
                    XYZ tempXYZ = null;
                    #region delete identical points, Distinct() linq not that smart
                    foreach (var item in temp)
                    {
                        if (tempXYZ == null)
                        {
                            tempXYZ = item;
                            Edges.Add(item);
                        }
                        else
                        {
                            bool isPresent = false;
                            foreach (var item2 in Edges)
                            {
                                if (item.X == item2.X &&
                                    item.Y == item2.Y &&
                                    item.Z == item2.Z)
                                {
                                    isPresent = true;
                                }
                            }
                            if (isPresent == false)
                            {
                                Edges.Add(item);
                            }
                        }
                    }
                    #endregion

                    Level currentLevel = null;
                    //Get the duct Type
                    FilteredElementCollector collector1 = new FilteredElementCollector(doc);
                    collector1.OfClass(typeof(DuctType));
                    DuctType ductType = null;
                    foreach (Element elem in collector1)
                    {
                        /**
                         * Raccord avec té et coude droit
                         *  Raccord par té avec coude segmenté
                         *  Raccord par piquage et coude segmenté
                         *  Raccord par té et coude droit
                         *  Raccord par piquage et coude droit
                         *  Raccord avec té et coude segmenté
                         *  Raccord par piquage et coude à rayon
                         *  Raccord par piquage et coude segmenté
                         *  Raccord par piquage et coude droit
                         *  Raccord par piquage et coude lisse
                         *  Raccord avec té et coude lisse
                         *  Synoptique de désenfumage
                         *  Raccord par piquage et coude droit chanfreiné
                         *  Raccord avec té et coude à rayon
                         **/
                        if (elem.Name == "Raccord avec té et coude lisse" ||
                            elem.Name == "Connection with tee and smooth elbow")    // gerer english
                        {
                            ductType = elem as DuctType;
                        }
                    }
                    FilteredElementCollector collector2 = new FilteredElementCollector(doc);
                    collector2.OfClass(typeof(MechanicalSystemType)).OfCategory(BuiltInCategory.OST_DuctSystem);
                    MechanicalSystemType mechType = null;
                    foreach (Element e1 in collector2)
                    {
                        /**
                         *  Désenfumage air neuf
                         *  Conduit de Fumée
                         *  Soufflage
                         *  Reprise
                         *  Extraction
                         *  VMC
                         *  Desenfumage Extraction
                         *  Air Neuf
                         *  Rejet
                         *  Desenfumage Air Neuf
                         *  Soufflage Recylage
                         *  Reprise Recyclage
                         *  Soufflage VC
                         *  Soufflage CTA
                         *  ..
                         **/
                        if (e1.Name == "VMC" || e1.Name == "CMV")  // gerer english
                        {
                            mechType = e1 as MechanicalSystemType;
                        }
                    }

                    /**
                     *  Get next space
                     **/


                    bool GetMe = false;
                    int  at    = 0;
                    foreach (var key in RevitDataContext.lazyInstance.SpacesInfo.Keys)
                    {
                        if (key.Number == space.Number)
                        {
                            GetMe = true;
                        }
                        if (GetMe == true)
                        {
                            if (at != 0)
                            {
                                at -= 1;
                            }
                            break;
                        }
                        at += 1;
                    }

                    currentLevel = e.Document.GetElement(e.LevelId) as Level;
                    XYZ startingPoint = null;
                    XYZ endingPoint   = null;

                    /**
                     *  Get the starting point shifted depending on next space location
                     * */

                    Utils.lazyInstance.GetLowestAndHighestPolygon(RevitDataContext.lazyInstance.SpacesInfo.ElementAt(i).Value.Item2, space.Level);
                    List <XYZ> test1 = new List <XYZ>();
                    List <XYZ> test2 = new List <XYZ>();
                    test1 = Utils.lazyInstance.lowestPolyg;
                    test2 = Utils.lazyInstance.highestPolyg;
                    if (test1.Count() != 0 && test2.Count() != 0)
                    {
                        startingPoint = Utils.lazyInstance.GetCenterOfPolygon(test1);
                        endingPoint   = Utils.lazyInstance.GetCenterOfPolygon(test2);
                    }

                    Utils.lazyInstance.GetLowestAndHighestPolygon(RevitDataContext.lazyInstance.SpacesInfo.ElementAt(correspSmallestSpaces[i]).Value.Item2,
                                                                  RevitDataContext.lazyInstance.SpacesInfo.ElementAt(correspSmallestSpaces[i]).Key.Level);
                    List <XYZ> test5 = new List <XYZ>();
                    List <XYZ> test6 = new List <XYZ>();
                    test5 = Utils.lazyInstance.lowestPolyg;
                    test6 = Utils.lazyInstance.highestPolyg;
                    XYZ SendingPoint = Utils.lazyInstance.GetCenterOfPolygon(test6);
                    startingPoint = Utils.lazyInstance.GetCenterOfPolygon(test5);
                    Duct      duct      = null;
                    Connector ductStart = null;
                    Connector ductEnd   = null;
                    Utils.lazyInstance.GetLowestAndHighestPolygon(RevitDataContext.lazyInstance.SpacesInfo.ElementAt(i).Value.Item2,
                                                                  RevitDataContext.lazyInstance.SpacesInfo.ElementAt(i).Key.Level);
                    List <XYZ> test3 = new List <XYZ>();
                    List <XYZ> test4 = new List <XYZ>();
                    test3       = Utils.lazyInstance.lowestPolyg;
                    test4       = Utils.lazyInstance.highestPolyg;
                    endingPoint = new XYZ(SendingPoint.X, SendingPoint.Y, Utils.lazyInstance.GetCenterOfPolygon(test4).Z);

                    if (tiltingSpaces.Contains(correspSmallestSpaces[i]) && i != RevitDataContext.lazyInstance.SpacesInfo.Count() - 1)
                    {
                        XYZ nSt = new XYZ(startingPoint.X - 0.1, startingPoint.Y, startingPoint.Z - 0.8);
                        startingPoint = nSt;
                    }
                    Debug.WriteLine("i: " + i);
                    if (!tiltingSpaces.Contains(i) || i == 0 || i == tiltingSpaces.LastOrDefault())
                    {
                        if (currentConn != null)
                        {
                            XYZ nStart1 = currentConnOrigin;
                            endingPoint = nStart1;
                        }
                        using (Transaction tr = new Transaction(doc))
                        {
                            tr.Start("Create New Duct");
                            {
                                if (currentConn == null)
                                {
                                    duct = Duct.Create(doc, mechType.Id, ductType.Id, RevitDataContext.lazyInstance.SpacesInfo.ElementAt(i).Key.LevelId, startingPoint, endingPoint);
                                }
                                else
                                {
                                    duct = Duct.Create(doc, ductType.Id, RevitDataContext.lazyInstance.SpacesInfo.ElementAt(i).Key.LevelId, currentConn, startingPoint);
                                    Debug.WriteLine("currentConn.Origin: " + currentConn.Origin);
                                    Debug.WriteLine("startingPoint Origin: " + startingPoint);
                                }


                                Parameter parameter = duct.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM);
                                parameter.Set(diameter);
                                List <Connector> lC = new List <Connector>();
                                foreach (Connector conn in duct.ConnectorManager.Connectors)
                                {
                                    if (conn.ConnectorType == ConnectorType.End)
                                    {
                                        lC.Add(conn);
                                    }
                                }

                                if (lC.ElementAt(0).Origin.Z > lC.ElementAt(1).Origin.Z)
                                {
                                    ductStart = lC.ElementAt(1);
                                    ductEnd   = lC.ElementAt(0);
                                }
                                else
                                {
                                    ductStart = lC.ElementAt(0);
                                    ductEnd   = lC.ElementAt(1);
                                }
                                if (currentConn == null)
                                {
                                    currentConnectors.Add("start" + i, ductStart);
                                    currentConnectors.Add("end" + i, ductEnd);
                                }
                                else
                                {
                                    currentConnectors.Add("start" + i, currentConn);
                                    currentConnectors.Add("end" + i, ductEnd);
                                    doc.Create.NewElbowFitting(ductStart, currentConn);
                                }
                                Debug.WriteLine("Passed, ductStart.Origin : " + ductStart.Origin);
                                tr.Commit();
                                currentConn = ductEnd;
                            }
                        }
                    }

                    // is getting tilted
                    if (tiltingSpaces.Contains(correspSmallestSpaces[i]) &&
                        i != RevitDataContext.lazyInstance.SpacesInfo.Count() - 1 &&
                        correspSmallestSpaces[i] != RevitDataContext.lazyInstance.SpacesInfo.Count() - 1)
                    {
                        Utils.lazyInstance.GetLowestAndHighestPolygon(RevitDataContext.lazyInstance.SpacesInfo.ElementAt(correspSmallestSpaces[i + 1]).Value.Item2,
                                                                      RevitDataContext.lazyInstance.SpacesInfo.ElementAt(correspSmallestSpaces[i + 1]).Key.Level);
                        List <XYZ> test7 = new List <XYZ>();
                        test7 = Utils.lazyInstance.lowestPolyg;
                        var tempZ = startingPoint.Z;
                        endingPoint = new XYZ(Utils.lazyInstance.GetCenterOfPolygon(test7).X, Utils.lazyInstance.GetCenterOfPolygon(test7).Y, tempZ);

                        if (currentConn != null)
                        {
                            Utils.lazyInstance.GetLowestAndHighestPolygon(RevitDataContext.lazyInstance.SpacesInfo.ElementAt(correspSmallestSpaces[correspSmallestSpaces[i] + 1]).Value.Item2,
                                                                          RevitDataContext.lazyInstance.SpacesInfo.ElementAt(correspSmallestSpaces[i + 1]).Key.Level);
                            List <XYZ> test77 = new List <XYZ>();
                            test77 = Utils.lazyInstance.lowestPolyg;
                            var tempZZ = startingPoint.Z;
                            endingPoint = new XYZ(Utils.lazyInstance.GetCenterOfPolygon(test77).X, Utils.lazyInstance.GetCenterOfPolygon(test77).Y, tempZ);
                        }

                        using (Transaction tr2 = new Transaction(doc))
                        {
                            tr2.Start("Create New Tilting Duct");
                            {
                                duct = Duct.Create(doc, mechType.Id, ductType.Id, RevitDataContext.lazyInstance.SpacesInfo.ElementAt(i).Key.LevelId, startingPoint, endingPoint);
                                Debug.WriteLine("startingPoint Origin: " + startingPoint);
                                Debug.WriteLine("endingPoint.Origin: " + endingPoint);

                                Parameter parameter = duct.get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM);
                                parameter.Set(diameter);
                                List <Connector> lC = new List <Connector>();
                                foreach (Connector conn in duct.ConnectorManager.Connectors)
                                {
                                    if (conn.ConnectorType == ConnectorType.End)
                                    {
                                        lC.Add(conn);
                                    }
                                }
                                int tempi = i + 1;
                                if (i != 0)
                                {
                                    tempi = correspSmallestSpaces[correspSmallestSpaces[i] + 1];
                                }
                                // getting the right start and end duct
                                Utils.lazyInstance.GetLowestAndHighestPolygon(RevitDataContext.lazyInstance.SpacesInfo.ElementAt(tempi).Value.Item2,
                                                                              RevitDataContext.lazyInstance.SpacesInfo.ElementAt(tempi).Key.Level);

                                List <XYZ> test8 = new List <XYZ>();
                                test8     = Utils.lazyInstance.lowestPolyg;
                                lC        = Utils.lazyInstance.GetClosestConnector(lC, Utils.lazyInstance.GetCenterOfPolygon(test8));
                                ductStart = lC.ElementAt(0);
                                ductEnd   = lC.ElementAt(1);

                                currentConnOrigin = ductStart.Origin;
                                test11            = ductEnd.Origin;
                                Debug.WriteLine("Start of tilting is :" + ductStart.Origin);
                                Debug.WriteLine("end of tilting is :" + ductEnd.Origin);
                                currentConn = ductStart;
                                doc.Create.NewElbowFitting(ductEnd, currentConnectors.ElementAt(currentConnectors.Count() - 1).Value);
                                currentConnectors.Add("startTilted" + i, ductStart);
                                currentConnectors.Add("endTilted" + i, ductEnd);
                            }
                            tr2.Commit();
                        }
                    }
                    i = correspSmallestSpaces[i] + 1;
                    currentElement = e;
                }
                catch (Exception ex)
                {
                    break;
                }
            }
        }
Ejemplo n.º 4
0
        /***************************************************/
        /****              Public methods               ****/
        /***************************************************/

        public static Duct ToRevitDuct(this oM.MEP.System.Duct duct, Document document, RevitSettings settings = null, Dictionary <Guid, List <int> > refObjects = null)
        {
            if (document == null)
            {
                return(null);
            }

            // Check valid duct object
            if (duct == null)
            {
                return(null);
            }

            // Construct Revit Duct
            Duct revitDuct = refObjects.GetValue <Duct>(document, duct.BHoM_Guid);

            if (revitDuct != null)
            {
                return(revitDuct);
            }

            // Settings
            settings = settings.DefaultIfNull();

            // Duct type
            DuctType ductType = duct.SectionProperty.ToRevitElementType(document, new List <BuiltInCategory> {
                BuiltInCategory.OST_DuctSystem
            }, settings, refObjects) as DuctType;

            if (ductType == null)
            {
                BH.Engine.Reflection.Compute.RecordError("No valid family has been found in the Revit model. Duct creation requires the presence of the default Duct Family Type.");
                return(null);
            }

            // End points
            XYZ start = duct.StartPoint.ToRevit();
            XYZ end   = duct.EndPoint.ToRevit();

            // Level
            Level level = document.LevelBelow(Math.Min(start.Z, end.Z), settings);

            if (level == null)
            {
                return(null);
            }

            // Default system used for now
            // TODO: in the future you could look for the existing connectors and check if any of them overlaps with start/end of this duct - if so, use it in Duct.Create.
            // hacky/heavy way of getting all connectors in the link below - however, i would rather filter the connecting elements out by type/bounding box first for performance reasons
            // https://thebuildingcoder.typepad.com/blog/2010/06/retrieve-mep-elements-and-connectors.html

            MechanicalSystemType mst = new FilteredElementCollector(document).OfClass(typeof(MechanicalSystemType)).OfType <MechanicalSystemType>().FirstOrDefault();

            if (mst == null)
            {
                BH.Engine.Reflection.Compute.RecordError("No valid MechanicalSystemType can be found in the Revit model. Creating a revit Duct requires a MechanicalSystemType.");
                return(null);
            }

            BH.Engine.Reflection.Compute.RecordWarning("Duct creation will utilise the first available MechanicalSystemType from the Revit model.");

            SectionProfile sectionProfile = duct.SectionProperty?.SectionProfile;

            if (sectionProfile == null)
            {
                BH.Engine.Reflection.Compute.RecordError("Duct creation requires a valid SectionProfile.");
                return(null);
            }

            DuctSectionProperty ductSectionProperty = duct.SectionProperty;

            // Create Revit Duct
            revitDuct = Duct.Create(document, mst.Id, ductType.Id, level.Id, start, end);
            if (revitDuct == null)
            {
                BH.Engine.Reflection.Compute.RecordError("No Revit Duct has been created. Please check inputs prior to push attempt.");
                return(null);
            }

            // Copy parameters from BHoM object to Revit element
            revitDuct.CopyParameters(duct, settings);

            double orientationAngle = duct.OrientationAngle;

            if (Math.Abs(orientationAngle) > settings.AngleTolerance)
            {
                ElementTransformUtils.RotateElement(document, revitDuct.Id, Line.CreateBound(start, end), orientationAngle);
            }

            double flowRate = duct.FlowRate;

            revitDuct.SetParameter(BuiltInParameter.RBS_DUCT_FLOW_PARAM, flowRate);

            double hydraulicDiameter = ductSectionProperty.HydraulicDiameter;

            revitDuct.SetParameter(BuiltInParameter.RBS_HYDRAULIC_DIAMETER_PARAM, hydraulicDiameter);

            DuctLiningType dlt = null;

            if (sectionProfile.LiningProfile != null)
            {
                // Get first available ductLiningType from document
                dlt = new FilteredElementCollector(document).OfClass(typeof(Autodesk.Revit.DB.Mechanical.DuctLiningType)).FirstOrDefault() as Autodesk.Revit.DB.Mechanical.DuctLiningType;
                if (dlt == null)
                {
                    BH.Engine.Reflection.Compute.RecordError("Any duct lining type needs to be present in the Revit model in order to push ducts with lining.\n" +
                                                             "Duct has been created but no lining has been applied.");
                }
            }

            DuctInsulationType dit = null;

            if (sectionProfile.InsulationProfile != null)
            {
                dit = new FilteredElementCollector(document).OfClass(typeof(Autodesk.Revit.DB.Mechanical.DuctInsulationType)).FirstOrDefault() as Autodesk.Revit.DB.Mechanical.DuctInsulationType;
                if (dit == null)
                {
                    BH.Engine.Reflection.Compute.RecordError("Any duct insulation type needs to be present in the Revit model in order to push ducts with lining.\n" +
                                                             "Duct has been created but no insulation has been applied.");
                }
            }

            // Rectangular Duct
            if (sectionProfile.ElementProfile is BoxProfile)
            {
                BoxProfile elementProfile = sectionProfile.ElementProfile as BoxProfile;

                // Set Height
                double profileHeight = elementProfile.Height;
                revitDuct.SetParameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM, profileHeight);

                // Set Width
                double profileWidth = elementProfile.Width;
                revitDuct.SetParameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM, profileWidth);

                // Set LiningProfile
                if (dlt != null)
                {
                    BoxProfile liningProfile   = sectionProfile.LiningProfile as BoxProfile;
                    double     liningThickness = liningProfile.Thickness;
                    // Create ductLining
                    Autodesk.Revit.DB.Mechanical.DuctLining dl = Autodesk.Revit.DB.Mechanical.DuctLining.Create(document, revitDuct.Id, dlt.Id, liningThickness);
                }

                // Set InsulationProfile
                if (dit != null)
                {
                    BoxProfile insulationProfile   = sectionProfile.InsulationProfile as BoxProfile;
                    double     insulationThickness = insulationProfile.Thickness;
                    // Create ductInsulation
                    Autodesk.Revit.DB.Mechanical.DuctInsulation di = Autodesk.Revit.DB.Mechanical.DuctInsulation.Create(document, revitDuct.Id, dit.Id, insulationThickness);
                }

                // Set EquivalentDiameter
                double circularEquivalentDiameter = ductSectionProperty.CircularEquivalentDiameter;
                revitDuct.SetParameter(BuiltInParameter.RBS_EQ_DIAMETER_PARAM, circularEquivalentDiameter);
            }
            else if (sectionProfile.ElementProfile is TubeProfile)
            {
                TubeProfile elementProfile = sectionProfile.ElementProfile as TubeProfile;

                double diameter = elementProfile.Diameter;
                revitDuct.SetParameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM, diameter);

                // Set LiningProfile
                if (dlt != null)
                {
                    TubeProfile liningProfile   = sectionProfile.LiningProfile as TubeProfile;
                    double      liningThickness = liningProfile.Thickness;
                    //Create ductLining
                    Autodesk.Revit.DB.Mechanical.DuctLining dl = Autodesk.Revit.DB.Mechanical.DuctLining.Create(document, revitDuct.Id, dlt.Id, liningThickness);
                }

                // Set InsulationProfile
                if (dit != null)
                {
                    TubeProfile insulationProfile   = sectionProfile.InsulationProfile as TubeProfile;
                    double      insulationThickness = insulationProfile.Thickness;
                    // Create ductInsulation
                    Autodesk.Revit.DB.Mechanical.DuctInsulation di = Autodesk.Revit.DB.Mechanical.DuctInsulation.Create(document, revitDuct.Id, dit.Id, insulationThickness);
                }
            }

            refObjects.AddOrReplace(duct, revitDuct);
            return(revitDuct);
        }
Ejemplo n.º 5
0
        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);
        }