public AnalyticElement(Element element)
        {
            Element = element;

            Parameter parInsTypeCheck = Element.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_TYPE);

            if (parInsTypeCheck.HasValue)
            {
                Parameter parInsThickness = Element.get_Parameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
                InsulationThk = (int)parInsThickness.AsDouble().FtToMm().Round();
            }

            switch (Element)
            {
            case Pipe pipe:
                //Outside diameter
                oDia = Element.get_Parameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER).AsDouble().FtToMm();
                //Wallthk
                DN      = (int)pipe.Diameter.FtToMm().Round();
                WallThk = MepUtils.pipeWallThkDict()[DN];
                break;

            case FamilyInstance fi:
                //Outside diameter
                Cons cons = MepUtils.GetConnectors(fi);
                DN      = (int)(cons.Primary.Radius * 2).FtToMm().Round();
                oDia    = MepUtils.outerDiaDict()[DN];
                WallThk = MepUtils.pipeWallThkDict()[DN];
                break;

            default:
                break;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Remember to check for con.IsConnected!
        /// </summary>
        /// <param name="con">Connector for which to get the correspoinding ref con.</param>
        /// <param name="elem">The host element of the original connector.</param>
        /// <returns>The corresponding reference connector.</returns>
        public static Connector GetRefConnnector(this Connector con, Element elem)
        {
            var allRefsNotFiltered = MepUtils.GetAllConnectorsFromConnectorSet(con.AllRefs);
            var correspondingCon   = allRefsNotFiltered
                                     .Where(x => x.Domain == Domain.DomainPiping)
                                     .Where(x => x.Owner.Id.IntegerValue != elem.Id.IntegerValue).FirstOrDefault();

            return(correspondingCon);
        }
Esempio n. 3
0
        internal static XYZ OletP1Point(Cons cons)
        {
            XYZ endPointOriginOletPrimary   = cons.Primary.Origin;
            XYZ endPointOriginOletSecondary = cons.Secondary.Origin;

            //get reference elements
            var refCons = MepUtils.GetAllConnectorsFromConnectorSet(cons.Primary.AllRefs);

            Connector refCon = refCons.Where(x => x.Owner.IsType <Pipe>()).FirstOrDefault();

            if (refCon == null)
            {
                throw new Exception("refCon Owner cannot find a Pipe for element!");
            }
            Pipe refPipe = (Pipe)refCon.Owner;

            Cons refPipeCons = Shared.MepUtils.GetConnectors(refPipe);

            //Following code is ported from my python solution in Dynamo.
            //The olet geometry is analyzed with congruent rectangles to find the connection point on the pipe even for angled olets.
            XYZ    B = endPointOriginOletPrimary; XYZ D = endPointOriginOletSecondary; XYZ pipeEnd1 = refPipeCons.Primary.Origin; XYZ pipeEnd2 = refPipeCons.Secondary.Origin;
            XYZ    BDvector = D - B; XYZ ABvector = pipeEnd1 - pipeEnd2;
            double angle = Conversion.RadianToDegree(ABvector.AngleTo(BDvector));

            if (angle > 90)
            {
                ABvector = -ABvector;
                angle    = Conversion.RadianToDegree(ABvector.AngleTo(BDvector));
            }
            Line   refsLine = Line.CreateBound(pipeEnd1, pipeEnd2);
            XYZ    C        = refsLine.Project(B).XYZPoint;
            double L3       = B.DistanceTo(C);
            XYZ    E        = refsLine.Project(D).XYZPoint;
            double L4       = D.DistanceTo(E);
            double ratio    = L4 / L3;
            double L1       = E.DistanceTo(C);
            double L5       = L1 / (ratio - 1);
            XYZ    A;

            if (angle < 89)
            {
                XYZ ECvector = C - E;
                ECvector = ECvector.Normalize();
                double L = L1 + L5;
                ECvector = ECvector.Multiply(L);
                A        = E.Add(ECvector);
            }
            else
            {
                A = E;
            }
            return(A);
        }
        public void AnalyzeReducer()
        {
            int fromDN = (int)(From.NextCon.Radius * 2).FtToMm().Round();

            oDia    = MepUtils.outerDiaDict()[fromDN];
            WallThk = MepUtils.pipeWallThkDict()[fromDN];

            int toDN = (int)(To.PreviousCon.Radius * 2).FtToMm().Round();

            secondODia    = MepUtils.outerDiaDict()[toDN];
            secondWallThk = MepUtils.pipeWallThkDict()[toDN];
        }
        public void AnalyzeBend()
        {
            Cons   cons = MepUtils.GetConnectors(Element);
            XYZ    P    = cons.Primary.Origin;
            XYZ    Q    = cons.Secondary.Origin;
            double a    = P.DistanceTo(Q) / 2;

            double angle = Element.LookupParameter("Angle").AsDouble();
            double A     = angle / 2;

            BendRadius = (a / (Math.Sin(A))).FtToMm();
        }
Esempio n. 6
0
        public static int OletRefOwnerIdAsInt(this Element e)
        {
            var       cons    = MepUtils.GetConnectors(e);
            var       refCons = MepUtils.GetAllConnectorsFromConnectorSet(cons.Primary.AllRefs);
            Connector refCon  = refCons.Where(x => x.Owner.IsType <Pipe>()).FirstOrDefault();

            if (refCon == null)
            {
                throw new Exception("Olet id " + e.Id.ToString() + " has no reference connector! Check connectivity.");
            }
            Element owner = refCon.Owner;

            return(owner.Id.IntegerValue);
        }
        public NTR_Exporter_form(ExternalCommandData cData, string message)
        {
            InitializeComponent();
            _commandData = cData;
            _uiapp       = _commandData.Application;
            _uidoc       = _uiapp.ActiveUIDocument;
            _doc         = _uidoc.Document;
            _message     = message;

            //Init excel path
            _excelPath = mySettings.Default.excelPath;
            if (!string.IsNullOrEmpty(_excelPath))
            {
                iv.ExcelPath = _excelPath;
            }
            //textBox20.Text = _excelPath;

            //Init output path
            _outputDirectoryFilePath = mySettings.Default.textBox5OutputPath;
            if (!string.IsNullOrEmpty(_outputDirectoryFilePath))
            {
                iv.OutputDirectoryFilePath = mySettings.Default.textBox5OutputPath;
            }
            textBox5.Text = iv.OutputDirectoryFilePath;

            //Init Scope
            //Gather all physical piping systems and collect distinct abbreviations
            pipeLinesAbbreviations = MepUtils.GetDistinctPhysicalPipingSystemTypeNames(_doc);

            //Use the distinct abbreviations as data source for the comboBox
            comboBox2.DataSource = pipeLinesAbbreviations;

            iv.ExportAllOneFile       = mySettings.Default.radioButton1AllPipelines;
            iv.ExportAllSepFiles      = mySettings.Default.radioButton13AllPipelinesSeparate;
            iv.ExportSpecificPipeLine = mySettings.Default.radioButton2SpecificPipeline;
            iv.ExportSelection        = mySettings.Default.radioButton14ExportSelection;
            if (!iv.ExportSpecificPipeLine)
            {
                comboBox2.Visible = false;
                textBox4.Visible  = false;
            }

            //Init diameter limit
            iv.DiameterLimit = double.Parse(mySettings.Default.textBox22DiameterLimit);
        }
Esempio n. 8
0
        private Connector DetectUnconnectedConnector(Document doc, Connector knownCon)
        {
            var allCons = MepUtils.GetALLConnectorsInDocument(doc);

            return(allCons.Where(c => c.Equalz(knownCon, 0.00328) && c.Owner.Id.IntegerValue != knownCon.Owner.Id.IntegerValue).FirstOrDefault());
        }
Esempio n. 9
0
        public Cons(Element element, bool pipeConnectorsOrdered = false)
        {
            var connectors = MepUtils.GetALLConnectorsFromElements(element);

            switch (element)
            {
            case Pipe pipe:

                List <Connector> filteredCons = new List <Connector>();
                if (pipeConnectorsOrdered)
                {
                    filteredCons = connectors
                                   .Where(c => c.ConnectorType.ToString() == "End")
                                   .OrderBy(c => c.Origin.X.Round(1))
                                   .ThenBy(c => c.Origin.Y.Round(1))
                                   .ThenBy(c => c.Origin.Z.Round(1))
                                   .ToList();
                }
                else
                {
                    filteredCons = connectors.Where(c => c.ConnectorType.ToString() == "End").ToList();
                }

                Primary   = filteredCons.First();
                Secondary = filteredCons.Last();
                break;

            case FamilyInstance fi:
                foreach (Connector connector in connectors)
                {
                    MEPConnectorInfo mci = connector.GetMEPConnectorInfo();

                    Count++;

                    if (mci.IsPrimary)
                    {
                        Primary = connector;
                    }
                    else if (mci.IsSecondary)
                    {
                        Secondary = connector;
                    }
                    else
                    {
                        Tertiary = connector;
                    }
                }

                if (Count > 1 && Secondary == null)
                {
                    throw new Exception($"Element {element.Id.ToString()} has {Count} connectors and no secondary!");
                }

                if (element is FamilyInstance)
                {
                    if (element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting)
                    {
                        var mf = ((FamilyInstance)element).MEPModel as MechanicalFitting;

                        if (mf.PartType.ToString() == "Transition")
                        {
                            double primDia = (Primary.Radius * 2).Round(3);
                            double secDia  = (Secondary.Radius * 2).Round(3);

                            Largest  = primDia > secDia ? Primary : Secondary;
                            Smallest = primDia < secDia ? Primary : Secondary;
                        }
                    }
                }
                break;

            default:
                throw new Exception("Cons: Element id nr.: " + element.Id.ToString() + " is not a Pipe or FamilyInstance!");
            }
        }
        public PCF_Exporter_form(ExternalCommandData cData, string message)
        {
            InitializeComponent();
            _commandData = cData;
            _uiapp       = _commandData.Application;
            _uidoc       = _uiapp.ActiveUIDocument;
            _doc         = _uidoc.Document;
            _message     = message;

            //Init excel path
            _excelPath = mySettings.Default.excelPath;
            //textBox20.Text = _excelPath;

            //Init Scope

            //Gather all physical piping systems and collect distinct abbreviations
            pipeLinesAbbreviations = MepUtils.GetDistinctPhysicalPipingSystemTypeNames(_doc);

            //Use the distinct abbreviations as data source for the comboBox
            comboBox2.DataSource = pipeLinesAbbreviations;

            iv.ExportAllOneFile       = mySettings.Default.radioButton1AllPipelines;
            iv.ExportAllSepFiles      = mySettings.Default.radioButton13AllPipelinesSeparate;
            iv.ExportSpecificPipeLine = mySettings.Default.radioButton2SpecificPipeline;
            iv.ExportSelection        = mySettings.Default.radioButton14ExportSelection;
            if (!iv.ExportSpecificPipeLine)
            {
                comboBox2.Visible = false;
                textBox4.Visible  = false;
            }

            //Init Bore
            iv.UNITS_BORE_MM   = mySettings.Default.radioButton3BoreMM;
            iv.UNITS_BORE_INCH = mySettings.Default.radioButton4BoreINCH;
            iv.UNITS_BORE      = iv.UNITS_BORE_MM ? "MM" : "INCH";

            //Init cooords
            iv.UNITS_CO_ORDS_MM   = mySettings.Default.radioButton5CoordsMm;
            iv.UNITS_CO_ORDS_INCH = mySettings.Default.radioButton6CoordsInch;
            iv.UNITS_CO_ORDS      = iv.UNITS_CO_ORDS_MM ? "MM" : "INCH";

            //Init weight
            iv.UNITS_WEIGHT_KGS = mySettings.Default.radioButton7WeightKgs;
            iv.UNITS_WEIGHT_LBS = mySettings.Default.radioButton8WeightLbs;
            iv.UNITS_WEIGHT     = iv.UNITS_WEIGHT_KGS ? "KGS" : "LBS";

            //Init weight-length
            iv.UNITS_WEIGHT_LENGTH_METER = mySettings.Default.radioButton9WeightLengthM;
            iv.UNITS_WEIGHT_LENGTH_FEET  = mySettings.Default.radioButton10WeightLengthF;
            iv.UNITS_WEIGHT_LENGTH       = iv.UNITS_WEIGHT_LENGTH_METER ? "METER" : "FEET";

            //Init output path
            iv.OutputDirectoryFilePath = mySettings.Default.textBox5OutputPath;
            textBox5.Text = iv.OutputDirectoryFilePath;

            //Init diameter limit
            iv.DiameterLimit = double.Parse(mySettings.Default.textBox22DiameterLimit);

            //Init write wall thickness
            iv.WriteWallThickness = mySettings.Default.radioButton12WallThkTrue;

            //Init export to section
            iv.ExportToPlant3DIso = mySettings.Default.checkBox1Checked;
            iv.ExportToCII        = mySettings.Default.checkBox2Checked;
        }
Esempio n. 11
0
        internal Result ExecuteMyCommand(UIApplication uiApp, ref string msg)
        {
            // UIApplication uiApp = commandData.Application;
            //Test comment
            Document   doc   = uiApp.ActiveUIDocument.Document;
            UIDocument uidoc = uiApp.ActiveUIDocument;

            try
            {
                #region Declaration of variables
                // Instance a collector
                FilteredElementCollector collector = new FilteredElementCollector(doc);
                //FilteredElementCollector pipeTypeCollector = new FilteredElementCollector(doc); //Obsolete???

                // Define a Filter instance to filter by System Abbreviation
                ElementParameterFilter sysAbbr = Shared.Filter.ParameterValueGenericFilter(doc, InputVars.SysAbbr, InputVars.SysAbbrParam);

                // Declare pipeline grouping object
                IEnumerable <IGrouping <string, Element> > pipelineGroups;

                //Declare an object to hold collected elements from collector
                HashSet <Element> colElements = new HashSet <Element>();

                // Instance a collecting stringbuilder
                StringBuilder sbCollect = new StringBuilder();
                #endregion

                #region Compose preamble
                //Compose preamble
                Composer composer = new Composer();

                StringBuilder sbPreamble = composer.PreambleComposer();

                //Append preamble
                sbCollect.Append(sbPreamble);
                #endregion

                #region Element collectors
                //If user chooses to export a single pipeline get only elements in that pipeline and create grouping.
                //Grouping is necessary even tho theres only one group to be able to process by the same code as the all pipelines case

                //If user chooses to export all pipelines get all elements and create grouping
                if (InputVars.ExportAllOneFile)
                {
                    //Define a collector (Pipe OR FamInst) AND (Fitting OR Accessory OR Pipe).
                    //This is to eliminate FamilySymbols from collector which would throw an exception later on.
                    collector.WherePasses(new LogicalAndFilter(new List <ElementFilter>
                    {
                        new LogicalOrFilter(new List <ElementFilter>
                        {
                            new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting),
                            new ElementCategoryFilter(BuiltInCategory.OST_PipeAccessory),
                            new ElementClassFilter(typeof(Pipe))
                        }),
                        new LogicalOrFilter(new List <ElementFilter>
                        {
                            new ElementClassFilter(typeof(Pipe)),
                            new ElementClassFilter(typeof(FamilyInstance))
                        })
                    }));

                    colElements = collector.ToElements().ToHashSet();
                }

                else if (InputVars.ExportAllSepFiles || InputVars.ExportSpecificPipeLine)
                {
                    //Define a collector with multiple filters to collect PipeFittings OR PipeAccessories OR Pipes + filter by System Abbreviation
                    //System Abbreviation filter also filters FamilySymbols out.
                    collector.WherePasses(
                        new LogicalOrFilter(
                            new List <ElementFilter>
                    {
                        new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting),
                        new ElementCategoryFilter(BuiltInCategory.OST_PipeAccessory),
                        new ElementClassFilter(typeof(Pipe))
                    })).WherePasses(sysAbbr);
                    colElements = collector.ToElements().ToHashSet();
                }

                else if (InputVars.ExportSelection)
                {
                    ICollection <ElementId> selection = uiApp.ActiveUIDocument.Selection.GetElementIds();
                    colElements = selection.Select(s => doc.GetElement(s)).ToHashSet();
                }


                #region Sub: Filtering
                HashSet <Element> elements;
                try
                {
                    //DiameterLimit filter applied to ALL elements.
                    var filtering = from element in colElements where Filters.FilterDL(element) select element;

                    //Filter out EXCLUDED elements -> 0 means no checkmark
                    filtering = from element in filtering
                                where element.get_Parameter(new plst().PCF_ELEM_EXCL.Guid).AsInteger() == 0
                                select element;

                    //Filter out EXCLUDED pipelines -> 0 means no checkmark
                    filtering = filtering.Where(x => x.PipingSystemAllowed(doc) == true);

                    //Remove instrument pipes
                    filtering = filtering.ExceptWhere(x => x.get_Parameter(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM)
                                                      .AsString() == "INSTR");

                    //Filter out elements with specified PCF_ELEM_SPEC string
                    if (InputVars.PCF_ELEM_SPEC_FILTER.IsNullOrEmpty() == false)
                    {
                        filtering = filtering.ExceptWhere(x => x.get_Parameter(new plst().PCF_ELEM_SPEC.Guid).AsString() == InputVars.PCF_ELEM_SPEC_FILTER);
                    }

                    //If exporting to ISO, remove some not needed elements
                    if (InputVars.ExportToIsogen)
                    {
                        //When exporting to Plant3D ISO creation, remove the group with the Piping System: Analysis Rigids (ARGD)
                        filtering = filtering
                                    .Where(x => !(x.get_Parameter(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM).AsString() == "ARGD"));

                        ////Also remove anchor symbols -> not needed for ISO
                        ////Currently not removed -> used for floor symbols
                        //filtering = filtering.ExceptWhere(x => x
                        //    .get_Parameter(BuiltInParameter.ELEM_FAMILY_AND_TYPE_PARAM)
                        //    .AsValueString() == "Support Symbolic: ANC");
                    }

                    //Create a grouping of elements based on the Pipeline identifier (System Abbreviation)
                    pipelineGroups = from e in filtering
                                     group e by e.get_Parameter(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM).AsString();

                    elements = filtering.ToHashSet();
                }
                catch (Exception ex)
                {
                    throw new Exception("Filtering in Main threw an exception:\n" + ex.Message +
                                        "\nTo fix:\n" +
                                        "1. See if parameter PCF_ELEM_EXCL exists, if not, rerun parameter import.");
                }
                #endregion
                #endregion

                #region Initialize Material Data
                //TEST: Do not write material data to elements with EXISTING-INCLUDE spec
                //HashSet<Element> existInclElements = elements.Where(x =>
                //    x.get_Parameter(new plst().PCF_ELEM_SPEC.Guid).AsString() == "EXISTING-INCLUDE").ToHashSet();
                ////Remember the clearing of previous run data in transaction below

                //elements = elements.ExceptWhere(x =>
                //    x.get_Parameter(new plst().PCF_ELEM_SPEC.Guid).AsString() == "EXISTING-INCLUDE").ToHashSet();

                //Set the start number to count the COMPID instances and MAT groups.
                int elementIdentificationNumber = 0;
                int materialGroupIdentifier     = 0;

                //Make sure that every element has PCF_MAT_DESCR filled out.
                foreach (Element e in elements)
                {
                    if (string.IsNullOrEmpty(e.get_Parameter(new plst().PCF_MAT_DESCR.Guid).AsString()))
                    {
                        uidoc.Selection.SetElementIds(new List <ElementId>(1)
                        {
                            e.Id
                        });
                        BuildingCoderUtilities.ErrorMsg("PCF_MAT_DESCR is empty for element " + e.Id + "! Please, correct this issue before exporting again.");
                        throw new Exception("PCF_MAT_DESCR is empty for element " + e.Id + "! Please, correct this issue before exporting again.");
                    }
                }

                //Initialize material group numbers on the elements
                IEnumerable <IGrouping <string, Element> > materialGroups = from e in elements group e by e.get_Parameter(new plst().PCF_MAT_DESCR.Guid).AsString();

                using (Transaction trans = new Transaction(doc, "Set PCF_ELEM_COMPID and PCF_MAT_ID"))
                {
                    trans.Start();
                    //Clear MTL data from previous runs for elements with EXISTING-INCLUDE spec
                    //foreach (Element e in existInclElements)
                    //{
                    //    e.get_Parameter(new plst().PCF_ELEM_COMPID.Guid).Set("");
                    //    e.get_Parameter(new plst().PCF_MAT_ID.Guid).Set("");
                    //}

                    //Access groups
                    foreach (IEnumerable <Element> group in materialGroups)
                    {
                        materialGroupIdentifier++;
                        //Access parameters
                        foreach (Element element in group)
                        {
                            elementIdentificationNumber++;
                            element.get_Parameter(new plst().PCF_ELEM_COMPID.Guid).Set(elementIdentificationNumber.ToString());
                            element.get_Parameter(new plst().PCF_MAT_ID.Guid).Set(materialGroupIdentifier.ToString());
                        }
                    }
                    trans.Commit();
                }

                //If turned on, write wall thickness of all components
                if (InputVars.WriteWallThickness)
                {
                    //Assign correct wall thickness to elements.
                    using (Transaction trans1 = new Transaction(doc))
                    {
                        trans1.Start("Set wall thickness for pipes!");
                        ParameterDataWriter.SetWallThicknessPipes(elements);
                        trans1.Commit();
                    }
                }

                #endregion

                using (TransactionGroup txGp = new TransactionGroup(doc))
                {
                    txGp.Start("Bogus transactionGroup for the break in hangers");
                    #region Pipeline management
                    foreach (IGrouping <string, Element> gp in pipelineGroups)
                    {
                        HashSet <Element> pipeList = (from element in gp
                                                      where element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves
                                                      select element).ToHashSet();
                        HashSet <Element> fittingList = (from element in gp
                                                         where element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting
                                                         select element).ToHashSet();
                        HashSet <Element> accessoryList = (from element in gp
                                                           where element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeAccessory
                                                           select element).ToHashSet();

                        StringBuilder sbPipeline           = new PCF_Pipeline.PCF_Pipeline_Export().Export(gp.Key, doc);
                        StringBuilder sbFilename           = PCF_Pipeline.Filename.BuildAndWriteFilename(doc);
                        StringBuilder sbEndsAndConnections = PCF_Pipeline.EndsAndConnections
                                                             .DetectAndWriteEndsAndConnections(gp.Key, pipeList, fittingList, accessoryList, doc);

                        #region BrokenPipes

                        //Here be code to handle break in accessories that act as supports
                        //Find the supports in current acessoryList and add to supportList
                        //Instantiate a brokenPipesGroup class

                        //Collect all Connectors from brokenPipesList and find the longest distance
                        //Create a temporary pipe from the Connectors with longest distance
                        //Copy PCF_ELEM parameter values to the temporary pipe
                        //Add the temporary pipe to the pipeList
                        //Roll back the TransactionGroup after the elements are sent to Export class' Export methods.

                        List <BrokenPipesGroup> bpgList = new List <BrokenPipesGroup>();

                        List <Element> supportsList = accessoryList.Where(x => x.ComponentClass1(doc) == "Pipe Support").ToList();

                        while (supportsList.Count > 0)
                        {
                            //Get an element to start traversing
                            Element seedElement = supportsList.FirstOrDefault();
                            if (seedElement == null)
                            {
                                throw new Exception("BrokenPipes: Seed element returned null! supportsList.Count is " + supportsList.Count);
                            }

                            //Instantiate the BrokenPipesGroup
                            BrokenPipesGroup bpg = new BrokenPipesGroup(seedElement, gp.Key);

                            //Traverse system
                            bpg.Traverse(doc);

                            //Remove the support Elements from the collection to keep track of the while loop
                            foreach (Element support in bpg.SupportsOnPipe)
                            {
                                supportsList = supportsList.ExceptWhere(x => x.Id.IntegerValue == support.Id.IntegerValue).ToList();
                            }

                            bpgList.Add(bpg);
                        }

                        using (Transaction tx = new Transaction(doc))
                        {
                            tx.Start("Create healed pipes");
                            foreach (BrokenPipesGroup bpg in bpgList)
                            {
                                //Remove the broken pipes from the pipeList
                                //If there's only one broken pipe, then there's no need to do anything
                                //If there's no broken pipes, then there's no need to do anything either
                                if (bpg.BrokenPipes.Count != 0 && bpg.BrokenPipes.Count != 1)
                                {
                                    foreach (Element pipe in bpg.BrokenPipes)
                                    {
                                        pipeList = pipeList.ExceptWhere(x => x.Id.IntegerValue == pipe.Id.IntegerValue).ToHashSet();
                                    }

                                    //Using the new IEqualityComparer for Connectors to get distinct connectors in the collection
                                    var brokenCons = MepUtils.GetALLConnectorsFromElements(bpg.BrokenPipes.ToHashSet(), new ConnectorXyzComparer(2.0.MmToFt()));
                                    //Create distinct pair combinations with distance from all broken connectors
                                    //https://stackoverflow.com/a/47003122/6073998
                                    List <(Connector c1, Connector c2, double dist)> pairs = brokenCons
                                                                                             .SelectMany
                                                                                             (
                                        (fst, i) => brokenCons.Skip(i + 1).Select(snd => (fst, snd, fst.Origin.DistanceTo(snd.Origin)))
                                                                                             )
                                                                                             .ToList();
                                    var  longest = pairs.MaxBy(x => x.dist).FirstOrDefault();
                                    Pipe dPipe   = (Pipe)longest.c1.Owner;
                                    bpg.HealedPipe = Pipe.Create(doc, dPipe.MEPSystem.GetTypeId(), dPipe.GetTypeId(),
                                                                 dPipe.ReferenceLevel.Id, longest.c1.Origin, longest.c2.Origin);

                                    Pipe donorPipe = (Pipe)bpg.BrokenPipes.FirstOrDefault();
                                    bpg.HealedPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(donorPipe.Diameter);

                                    //Add the healed pipe to the pipeList for processing
                                    pipeList.Add(bpg.HealedPipe);
                                }
                            }
                            tx.Commit();
                        }

                        //Now the healed pipe must be populated by the parameters from a donorPipe
                        using (Transaction tx = new Transaction(doc))
                        {
                            //Gather all relevant parameter definitions
                            List <pdef> plist = new plst().LPAll.Where(x => x.Domain == "ELEM" && x.Usage == "U").ToList();
                            plist.Add(new plst().PCF_MAT_ID);

                            tx.Start("Populate the HealedPipe parameters!");
                            foreach (BrokenPipesGroup bpg in bpgList)
                            {
                                //Skip iteration if there's only 1 or no broken pipes
                                if (bpg.BrokenPipes.Count == 0 || bpg.BrokenPipes.Count == 1)
                                {
                                    continue;
                                }
                                Element donorPipe = bpg.BrokenPipes.FirstOrDefault();

                                foreach (pdef p in plist)
                                {
                                    Parameter donorParameter = donorPipe.get_Parameter(p.Guid);
                                    if (donorParameter == null)
                                    {
                                        continue;
                                    }
                                    switch (donorParameter.StorageType)
                                    {
                                    case StorageType.None:
                                        continue;

                                    case StorageType.Integer:
                                        int donorInt = donorParameter.AsInteger();
                                        if (donorInt == 0)
                                        {
                                            continue;
                                        }
                                        Parameter targetParInt = bpg.HealedPipe.get_Parameter(p.Guid);
                                        targetParInt.Set(donorInt);
                                        break;

                                    case StorageType.Double:
                                        continue;

                                    case StorageType.String:
                                        string donorStr = donorParameter.AsString();
                                        if (donorStr.IsNullOrEmpty())
                                        {
                                            continue;
                                        }
                                        Parameter targetParStr = bpg.HealedPipe.get_Parameter(p.Guid);
                                        targetParStr.Set(donorStr);
                                        break;

                                    case StorageType.ElementId:
                                        continue;

                                    default:
                                        continue;
                                    }
                                }
                            }
                            tx.Commit();
                        }

                        #endregion

                        StringBuilder sbPipes       = new PCF_Pipes.PCF_Pipes_Export().Export(gp.Key, pipeList, doc);
                        StringBuilder sbFittings    = new PCF_Fittings.PCF_Fittings_Export().Export(gp.Key, fittingList, doc);
                        StringBuilder sbAccessories = new PCF_Accessories.PCF_Accessories_Export().Export(gp.Key, accessoryList, doc);

                        sbCollect.Append(sbPipeline); sbCollect.Append(sbFilename); sbCollect.Append(sbEndsAndConnections);
                        sbCollect.Append(sbPipes); sbCollect.Append(sbFittings); sbCollect.Append(sbAccessories);
                    }
                    #endregion

                    txGp.RollBack(); //RollBack the temporary created elements
                }

                #region Materials
                StringBuilder sbMaterials = composer.MaterialsSection(materialGroups);
                sbCollect.Append(sbMaterials);
                #endregion

                #region Output
                // Output the processed data
                PCF_Output.Output output = new PCF_Output.Output();
                output.OutputWriter(sbCollect);
                #endregion
            }

            catch (Autodesk.Revit.Exceptions.OperationCanceledException)
            {
                return(Result.Cancelled);
            }

            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return(Result.Succeeded);
        }
 public AnalyticModel(HashSet <Element> elements)
 {
     AllElements   = elements.ToList();
     AllConnectors = MepUtils.GetALLConnectorsFromElements(elements).ToList();
 }
        public void AnalyzeSystem()
        {
            //Deviously hard to follow (and debug) code be here
            //Start analysis
            var openEnds = detectOpenEnds(Model);

            Connector        To          = null;
            Connector        From        = null;
            Node             FromNode    = null;
            Node             ToNode      = null;
            Element          curElem     = null;
            AnalyticElement  curAElem    = null;
            AnalyticSequence curSequence = null;

            bool continueSequence = false;

            IList <Connector> branchEnds = new List <Connector>();

            for (int i = 0; i < Model.AllElements.Count; i++)
            {
                if (!continueSequence)
                {
                    if (branchEnds.Count > 0)
                    {
                        From       = branchEnds.FirstOrDefault();
                        branchEnds = branchEnds.ExceptWhere(c => c.Equalz(From, _1mmTol)).ToList();
                        FromNode   = (from Node n in Model.AllNodes
                                      where n.PreviousCon != null && n.PreviousCon.Equalz(From, _1mmTol)
                                      select n).FirstOrDefault();
                        FromNode.NextCon = From;
                    }
                    else
                    {
                        From             = openEnds.FirstOrDefault();
                        openEnds         = openEnds.ExceptWhere(c => c.Equalz(From, _1mmTol)).ToList();
                        FromNode         = new Node();
                        FromNode.NextCon = From;
                        Model.AllNodes.Add(FromNode);



                        curSequence = new AnalyticSequence();
                    }

                    ToNode = new Node();

                    curElem  = From.Owner;
                    curAElem = new AnalyticElement(curElem);

                    continueSequence = true;
                }

                switch (curElem)
                {
                case Pipe pipe:

                    To = (from Connector c in pipe.ConnectorManager.Connectors     //End of the host/dummy pipe
                          where c.Id != From.Id && (int)c.ConnectorType == 1
                          select c).FirstOrDefault();

                    //Test if the ToNode already exists
                    //TODO: This test must be copied to all other elements
                    Node existingToNode = (from Node n in Model.AllNodes
                                           where
                                           (n.PreviousCon != null && n.PreviousCon.Equalz(To, _1mmTol)) ||
                                           (n.NextCon != null && n.NextCon.Equalz(To, _1mmTol))
                                           select n).FirstOrDefault();

                    if (existingToNode != null)
                    {
                        ToNode = existingToNode;
                        if (ToNode.PreviousCon == null)
                        {
                            ToNode.PreviousCon = To;
                        }
                        else if (ToNode.NextCon == null)
                        {
                            ToNode.NextCon = To;
                        }
                    }
                    else
                    {
                        ToNode.PreviousCon = To;
                        Model.AllNodes.Add(ToNode);
                    }

                    curAElem.From = FromNode;
                    curAElem.To   = ToNode;

                    //Assign correct element type to analytic element
                    curAElem.Type = ElemType.Pipe;

                    curSequence.Sequence.Add(curAElem);

                    break;

                case FamilyInstance fi:
                    Cons cons = MepUtils.GetConnectors(fi);
                    int  cat  = fi.Category.Id.IntegerValue;
                    switch (cat)
                    {
                    case (int)BuiltInCategory.OST_PipeFitting:
                        var mf       = fi.MEPModel as MechanicalFitting;
                        var partType = mf.PartType;
                        switch (partType)
                        {
                        case PartType.Elbow:
                            //First Analytic Element
                            XYZ elbowLoc = ((LocationPoint)fi.Location).Point;
                            ToNode.PreviousLoc = elbowLoc;         //The node has only element Location point defining it -
                            ToNode.NextLoc     = elbowLoc;         //and not two adjacent Connectors as element connection nodes
                            ToNode.Type        = ElemType.Elbow;
                            Model.AllNodes.Add(ToNode);

                            curAElem.From = FromNode;
                            curAElem.To   = ToNode;

                            curAElem.Type = ElemType.Elbow;

                            curAElem.AnalyzeBend();

                            curSequence.Sequence.Add(curAElem);

                            //Second Analytic Element
                            //First determine the To connector
                            To = (from Connector c in MepUtils.GetALLConnectorsFromElements(curElem)
                                  where c.Id != From.Id
                                  select c).FirstOrDefault();

                            FromNode = ToNode;             //Switch to next element
                            ToNode   = new Node();
                            Model.AllNodes.Add(ToNode);
                            ToNode.PreviousCon = To;
                            curAElem           = new AnalyticElement(curElem);
                            curAElem.From      = FromNode;
                            curAElem.To        = ToNode;

                            curAElem.Type = ElemType.Pipe;

                            curSequence.Sequence.Add(curAElem);
                            break;

                        case PartType.Tee:
                            //Junction logic
                            Node primNode = null;
                            Node secNode  = null;
                            Node tertNode = null;

                            //First analytic element
                            XYZ teeLoc = ((LocationPoint)fi.Location).Point;
                            ToNode.PreviousLoc = teeLoc;         //The node has only element Location point defining it -
                            ToNode.NextLoc     = teeLoc;         //and not two adjacent Connectors as element connection nodes
                            ToNode.Type        = ElemType.Tee;
                            Model.AllNodes.Add(ToNode);

                            curAElem.From = FromNode;
                            curAElem.To   = ToNode;

                            curAElem.Type = ElemType.Tee;

                            curSequence.Sequence.Add(curAElem);

                            //Logic to return correct node to next element
                            if (From.GetMEPConnectorInfo().IsPrimary)
                            {
                                primNode = FromNode;
                            }
                            else if (From.GetMEPConnectorInfo().IsSecondary)
                            {
                                secNode = FromNode;
                            }
                            else
                            {
                                tertNode = FromNode;
                            }

                            //From node is common for next two elements
                            FromNode = ToNode;

                            //Second Analytic Element
                            if (From.GetMEPConnectorInfo().IsPrimary)
                            {
                                To = cons.Secondary;
                            }
                            else if (From.GetMEPConnectorInfo().IsSecondary)
                            {
                                To = cons.Primary;
                            }
                            else
                            {
                                To = cons.Primary;
                            }

                            ToNode = new Node();
                            Model.AllNodes.Add(ToNode);
                            ToNode.PreviousCon = To;
                            curAElem           = new AnalyticElement(curElem);
                            curAElem.From      = FromNode;
                            curAElem.To        = ToNode;

                            curAElem.Type = ElemType.Pipe;

                            curSequence.Sequence.Add(curAElem);

                            //Logic to return correct node to next element
                            if (From.GetMEPConnectorInfo().IsPrimary)
                            {
                                secNode = ToNode;
                            }
                            else if (From.GetMEPConnectorInfo().IsSecondary)
                            {
                                primNode = ToNode;
                            }
                            else
                            {
                                primNode = ToNode;
                            }

                            //Third Analytic Element
                            if (From.GetMEPConnectorInfo().IsPrimary)
                            {
                                To = cons.Tertiary;
                            }
                            else if (From.GetMEPConnectorInfo().IsSecondary)
                            {
                                To = cons.Tertiary;
                            }
                            else
                            {
                                To = cons.Secondary;
                            }

                            ToNode = new Node();
                            Model.AllNodes.Add(ToNode);
                            ToNode.PreviousCon = To;
                            curAElem           = new AnalyticElement(curElem);
                            curAElem.From      = FromNode;
                            curAElem.To        = ToNode;

                            curAElem.Type = ElemType.Pipe;

                            curSequence.Sequence.Add(curAElem);

                            //Logic to return correct node to next element
                            if (From.GetMEPConnectorInfo().IsPrimary)
                            {
                                tertNode = ToNode;
                            }
                            else if (From.GetMEPConnectorInfo().IsSecondary)
                            {
                                tertNode = ToNode;
                            }
                            else
                            {
                                secNode = ToNode;
                            }

                            //Continuation logic
                            Connector candidate1;
                            Connector candidate2;

                            if (From.GetMEPConnectorInfo().IsPrimary)
                            {
                                candidate1 = (from Connector c in Model.AllConnectors
                                              where c.Equalz(cons.Secondary, _1mmTol)
                                              select c).FirstOrDefault();
                                candidate2 = (from Connector c in Model.AllConnectors
                                              where c.Equalz(cons.Tertiary, _1mmTol)
                                              select c).FirstOrDefault();

                                if (candidate1 != null)
                                {
                                    To     = cons.Secondary;
                                    ToNode = secNode;
                                    if (candidate2 != null)
                                    {
                                        branchEnds.Add(candidate2);
                                    }
                                }
                                else if (candidate2 != null)
                                {
                                    To     = cons.Tertiary;
                                    ToNode = tertNode;
                                }
                            }
                            else if (From.GetMEPConnectorInfo().IsSecondary)
                            {
                                candidate1 = (from Connector c in Model.AllConnectors
                                              where c.Equalz(cons.Primary, _1mmTol)
                                              select c).FirstOrDefault();
                                candidate2 = (from Connector c in Model.AllConnectors
                                              where c.Equalz(cons.Tertiary, _1mmTol)
                                              select c).FirstOrDefault();

                                if (candidate1 != null)
                                {
                                    To     = cons.Primary;
                                    ToNode = primNode;
                                    if (candidate2 != null)
                                    {
                                        branchEnds.Add(candidate2);
                                    }
                                }
                                else if (candidate2 != null)
                                {
                                    To     = cons.Tertiary;
                                    ToNode = tertNode;
                                }
                            }
                            else
                            {
                                candidate1 = (from Connector c in Model.AllConnectors
                                              where c.Equalz(cons.Primary, _1mmTol)
                                              select c).FirstOrDefault();
                                candidate2 = (from Connector c in Model.AllConnectors
                                              where c.Equalz(cons.Secondary, _1mmTol)
                                              select c).FirstOrDefault();

                                if (candidate1 != null)
                                {
                                    To     = cons.Primary;
                                    ToNode = primNode;
                                    if (candidate2 != null)
                                    {
                                        branchEnds.Add(candidate2);
                                    }
                                }
                                else if (candidate2 != null)
                                {
                                    To     = cons.Secondary;
                                    ToNode = secNode;
                                }
                            }
                            break;

                        case PartType.Transition:
                            To = (from Connector c in MepUtils.GetALLConnectorsFromElements(curElem)
                                  where c.Id != From.Id
                                  select c).FirstOrDefault();
                            ToNode.PreviousCon = To;
                            Model.AllNodes.Add(ToNode);

                            curAElem.From = FromNode;
                            curAElem.To   = ToNode;

                            //Assign correct element type to analytic element
                            curAElem.Type = ElemType.Transition;

                            //Determine start dia and second dia
                            curAElem.AnalyzeReducer();

                            curSequence.Sequence.Add(curAElem);
                            break;

                        case PartType.Cap:
                            //Handles flanges because of the workaround PartType.Cap for flanges
                            //Real Caps are ignored for now
                            To = (from Connector c in MepUtils.GetALLConnectorsFromElements(curElem)
                                  where c.Id != From.Id
                                  select c).FirstOrDefault();
                            ToNode.PreviousCon = To;
                            Model.AllNodes.Add(ToNode);

                            curAElem.From = FromNode;
                            curAElem.To   = ToNode;

                            //Assign correct element type to analytic element
                            curAElem.Type = ElemType.Rigid;

                            curSequence.Sequence.Add(curAElem);
                            break;

                        case PartType.Union:
                            throw new NotImplementedException();

                        case PartType.SpudAdjustable:
                            throw new NotImplementedException();

                        default:
                            continue;
                        }
                        break;

                    case (int)BuiltInCategory.OST_PipeAccessory:
                        if (From.GetMEPConnectorInfo().IsPrimary)
                        {
                            To = cons.Secondary;
                        }
                        else if (From.GetMEPConnectorInfo().IsSecondary)
                        {
                            To = cons.Primary;
                        }
                        else
                        {
                            throw new Exception("Something went wrong with connectors of element " + curElem.Id.ToString());
                        }

                        ToNode.PreviousCon = To;
                        Model.AllNodes.Add(ToNode);

                        curAElem.From = FromNode;
                        curAElem.To   = ToNode;

                        //Assign correct element type to analytic element
                        curAElem.Type = ElemType.Rigid;

                        curSequence.Sequence.Add(curAElem);
                        break;

                    default:
                        continue;
                    }
                    break;

                default:
                    continue;
                }

                //Prepare to restart iteration
                Model.AllConnectors = Model.AllConnectors.ExceptWhere(c => c.Owner.Id.IntegerValue == curElem.Id.IntegerValue).ToList();

                From = (from Connector c in Model.AllConnectors
                        where c.Equalz(To, _1mmTol)
                        select c).FirstOrDefault();

                if (From != null)
                {
                    curElem = From.Owner;

                    FromNode         = ToNode;
                    FromNode.NextCon = From;

                    ToNode = new Node();

                    curAElem = new AnalyticElement(curElem);
                }
                else
                {
                    continueSequence = false;
                    openEnds         = openEnds.ExceptWhere(c => c.Equalz(To, _1mmTol)).ToList();

                    if (branchEnds.Count > 0 && To != null)
                    {
                        branchEnds = branchEnds.ExceptWhere(c => c.Equalz(To, _1mmTol)).ToList();
                    }

                    if (branchEnds.Count < 1)
                    {
                        Model.Sequences.Add(curSequence);
                    }
                }
            }

            //Reference ALL analytic elements in the collecting pool
            foreach (var sequence in Model.Sequences)
            {
                foreach (var item in sequence.Sequence)
                {
                    Model.AllAnalyticElements.Add(item);
                }
            }

            //Loop over ALL nodes and populate coordinate information
            foreach (Node n in Model.AllNodes)
            {
                n.PopulateCoordinates();
            }

            BuildingCoderUtilities.InfoMsg(Model.AllNodes.Count.ToString());
        }
Esempio n. 14
0
        public static StringBuilder DetectAndWriteEndsAndConnections(
            string key, HashSet <Element> pipes, HashSet <Element> fittings, HashSet <Element> accessories, Document doc)
        {
            StringBuilder sb = new StringBuilder();

            HashSet <Element> all = new HashSet <Element>(pipes);

            all.UnionWith(fittings);
            all.UnionWith(accessories);

            //Iterate over all elements and check their connected counterparts
            //If they satisfy certain conditions -> write end continuation property
            //Cases for connected connectors:
            //1) In different PipingSystem -> Pipeline continuation
            //1.1) If Selection and connector belongs to an element not in selection -> Pipeline continuation
            //2) Belongs to MechanicalEquipment -> Equipment continuation -> write tags
            //3) Free end -> Null connection

            foreach (Element elem in all)
            {
                HashSet <Connector> cons = new HashSet <Connector>();

                switch (elem)
                {
                case Pipe pipe:
                    var consPipe = new Cons(elem);
                    cons.Add(consPipe.Primary);
                    cons.Add(consPipe.Secondary);
                    break;

                case FamilyInstance fi:
                    cons = MepUtils.GetALLConnectorsFromElements(elem);
                    break;

                default:
                    continue;
                }

                foreach (Connector con in cons)
                {
                    //This if should also filter out free ends...
                    if (con.IsConnected)
                    {
                        var allRefsNotFiltered = MepUtils.GetAllConnectorsFromConnectorSet(con.AllRefs);
                        var correspondingCon   = allRefsNotFiltered
                                                 .Where(x => x.Domain == Domain.DomainPiping)
                                                 .Where(x => x.Owner.Id.IntegerValue != elem.Id.IntegerValue).FirstOrDefault();

                        //CASE: Free end -> Do nothing yet, for simplicity
                        //This also catches empty cons on multicons accessories
                        //Example: pressure take outs on filters.
                        if (correspondingCon == null)
                        {
                            continue;
                        }

                        //CASE: If selection is exported, continuation for elements not in selection
                        //Even if same pipeline
                        if (iv.ExportSelection)
                        {
                            bool inElementsList = !all.Any(x => x.Id.IntegerValue == correspondingCon.Owner.Id.IntegerValue);
                            //bool inDiscardedPipes = !discardedPipes.Any(x => x.Id.IntegerValue == correspondingCon.Owner.Id.IntegerValue);

                            if (inElementsList)// && inDiscardedPipes)
                            {
                                //CASE: Con belongs to MechanicalEquipment
                                if (correspondingCon.Owner.Category.Id.IntegerValue == (int)BuiltInCategory.OST_MechanicalEquipment)
                                {
                                    sb.AppendLine("END-CONNECTION-EQUIPMENT");
                                    sb.Append(PCF_Functions.EndWriter.WriteCO(correspondingCon.Origin));
                                    sb.Append(PCF_Functions.ParameterDataWriter
                                              .ParameterValue("CONNECTION-REFERENCE", new[] { "TAG 1", "TAG 2", "TAG 3", "TAG 4" }, correspondingCon.Owner));

                                    continue;
                                }
                                //CASE: Any other component
                                else
                                {
                                    sb.AppendLine("END-CONNECTION-PIPELINE");
                                    sb.Append(PCF_Functions.EndWriter.WriteCO(correspondingCon.Origin));
                                    sb.AppendLine("    PIPELINE-REFERENCE " + correspondingCon.MEPSystemAbbreviation(doc));

                                    continue;
                                }
                            }
                            //CASE: None of the above hit -> continue with loop execution
                            //To prevent from falling through to non selection cases.
                            continue;
                        }

                        //CASE: Con belongs to MechanicalEquipment
                        else if (correspondingCon.Owner.Category.Id.IntegerValue == (int)BuiltInCategory.OST_MechanicalEquipment)
                        {
                            sb.AppendLine("END-CONNECTION-EQUIPMENT");
                            sb.Append(PCF_Functions.EndWriter.WriteCO(correspondingCon.Origin));
                            sb.Append(PCF_Functions.ParameterDataWriter
                                      .ParameterValue("CONNECTION-REFERENCE", new[] { "TAG 1", "TAG 2", "TAG 3", "TAG 4" }, correspondingCon.Owner));

                            continue;
                        }
                        //CASE: If corrCon belongs to different Pipeline -> unconditional end
                        //MechanicalEquipment cons should belong to the same Piping System, else...
                        else if (correspondingCon.MEPSystemAbbreviation(doc) != key)
                        {
                            sb.AppendLine("END-CONNECTION-PIPELINE");
                            sb.Append(PCF_Functions.EndWriter.WriteCO(correspondingCon.Origin));
                            sb.AppendLine("    PIPELINE-REFERENCE " + correspondingCon.MEPSystemAbbreviation(doc));

                            continue;
                        }
                        //CASE: If corrCon belongs to EXISTING component
                        //Write PIPELINE-REFERENCE -> EXISTING
                        Element hostElement = correspondingCon.Owner;
                        //GUID is for PCF_ELEM_SPEC
                        Parameter existingParameter = hostElement.get_Parameter(new Guid("90be8246-25f7-487d-b352-554f810fcaa7"));
                        if (existingParameter.AsString() == "EXISTING")
                        {
                            sb.AppendLine("END-CONNECTION-PIPELINE");
                            sb.Append(PCF_Functions.EndWriter.WriteCO(correspondingCon.Origin));
                            sb.AppendLine("    PIPELINE-REFERENCE EKSISTERENDE");
                        }
                    }
                }
            }

            return(sb);
        }
Esempio n. 15
0
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiApp = commandData.Application;
            Document      doc   = commandData.Application.ActiveUIDocument.Document;
            UIDocument    uidoc = uiApp.ActiveUIDocument;

            try
            {
                using (Transaction tx = new Transaction(doc))
                {
                    var allAccessories = fi.GetElements <Element, BuiltInCategory>(doc, BuiltInCategory.OST_PipeAccessory);

                    tx.Start("Populate tilkoblet");
                    foreach (var el in allAccessories)
                    {
                        Cons cons = new Cons(el);

                        Connector firstSideCon = cons.Primary; Connector secondSideCon = cons.Secondary;

                        Connector refFirstCon = null; Connector refSecondCon = null;

                        if (firstSideCon != null && firstSideCon.IsConnected)
                        {
                            var refFirstCons = MepUtils.GetAllConnectorsFromConnectorSet(firstSideCon.AllRefs);
                            refFirstCon = refFirstCons.FirstOrDefault();
                        }
                        else if (firstSideCon != null)
                        {
                            refFirstCon = DetectUnconnectedConnector(doc, firstSideCon);
                        }

                        if (secondSideCon != null && secondSideCon.IsConnected)
                        {
                            var refSecondCons = MepUtils.GetAllConnectorsFromConnectorSet(secondSideCon.AllRefs);
                            refSecondCon = refSecondCons.FirstOrDefault();
                        }
                        else if (secondSideCon != null)
                        {
                            refSecondCon = DetectUnconnectedConnector(doc, secondSideCon);
                        }

                        Element firstSideOwner = null; Element secondSideOwner = null;
                        string  commentsContent    = string.Empty;
                        string  firstSideComments  = string.Empty;
                        string  secondSideComments = string.Empty;

                        if (refFirstCon != null)
                        {
                            firstSideOwner = refFirstCon.Owner;
                            Parameter tag1par = firstSideOwner.LookupParameter("TAG 1");
                            if (tag1par != null)
                            {
                                string tag1 = firstSideOwner.LookupParameter("TAG 1").AsString();
                                string tag2 = firstSideOwner.LookupParameter("TAG 2").AsString();
                                string tag3 = firstSideOwner.LookupParameter("TAG 3").AsString();
                                string tag4 = firstSideOwner.LookupParameter("TAG 4").AsString();

                                firstSideComments = string.Empty;

                                if (!string.IsNullOrEmpty(tag1))
                                {
                                    firstSideComments += tag1;
                                }
                                if (!string.IsNullOrEmpty(tag2))
                                {
                                    firstSideComments += "_" + tag2;
                                }
                                if (!string.IsNullOrEmpty(tag3))
                                {
                                    firstSideComments += "_" + tag3;
                                }
                                if (!string.IsNullOrEmpty(tag4))
                                {
                                    firstSideComments += "_" + tag4;
                                }
                            }
                        }
                        if (refSecondCon != null)
                        {
                            secondSideOwner = refSecondCon.Owner;
                            Parameter tag1par = secondSideOwner.LookupParameter("TAG 1");
                            if (tag1par != null)
                            {
                                string tag1 = secondSideOwner.LookupParameter("TAG 1").AsString();
                                string tag2 = secondSideOwner.LookupParameter("TAG 2").AsString();
                                string tag3 = secondSideOwner.LookupParameter("TAG 3").AsString();
                                string tag4 = secondSideOwner.LookupParameter("TAG 4").AsString();

                                secondSideComments = string.Empty;

                                if (!string.IsNullOrEmpty(tag1))
                                {
                                    secondSideComments += tag1;
                                }
                                if (!string.IsNullOrEmpty(tag2))
                                {
                                    secondSideComments += "_" + tag2;
                                }
                                if (!string.IsNullOrEmpty(tag3))
                                {
                                    secondSideComments += "_" + tag3;
                                }
                                if (!string.IsNullOrEmpty(tag4))
                                {
                                    secondSideComments += "_" + tag4;
                                }
                            }
                        }

                        if (string.IsNullOrEmpty(firstSideComments) && string.IsNullOrEmpty(secondSideComments))
                        {
                            continue;
                        }
                        else if (string.IsNullOrEmpty(firstSideComments) || string.IsNullOrEmpty(secondSideComments))
                        {
                            if (!string.IsNullOrEmpty(firstSideComments))
                            {
                                commentsContent = firstSideComments;
                            }
                            else if (!string.IsNullOrEmpty(secondSideComments))
                            {
                                commentsContent = secondSideComments;
                            }
                        }
                        else
                        {
                            commentsContent = $"{firstSideComments}; {secondSideComments}";
                        }

                        Parameter comments = el.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS);
                        comments.Set(commentsContent);
                    }

                    tx.Commit();
                    return(Result.Succeeded);
                }
            }

            catch (Autodesk.Revit.Exceptions.OperationCanceledException) { return(Result.Cancelled); }

            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
Esempio n. 16
0
        public Result ExportNtr(ExternalCommandData cData)
        {
            // UIApplication uiApp = commandData.Application;
            Document doc = cData.Application.ActiveUIDocument.Document;

            try
            {
                #region Declaration of variables
                // Instance a collector
                FilteredElementCollector collector = new FilteredElementCollector(doc);

                // Define a Filter instance to filter by System Abbreviation
                ElementParameterFilter sysAbbr = Shared.Filter.ParameterValueGenericFilter(doc, InputVars.SysAbbr, InputVars.SysAbbrParam);

                // Declare pipeline grouping object
                IEnumerable <IGrouping <string, Element> > pipelineGroups;

                //Declare an object to hold collected elements from collector
                HashSet <Element> colElements = new HashSet <Element>();
                #endregion

                #region Element collectors
                //If user chooses to export a single pipeline get only elements in that pipeline and create grouping.
                //Grouping is necessary even tho theres only one group to be able to process by the same code as the all pipelines case

                //If user chooses to export all pipelines get all elements and create grouping
                if (iv.ExportAllOneFile)
                {
                    //Define a collector (Pipe OR FamInst) AND (Fitting OR Accessory OR Pipe).
                    //This is to eliminate FamilySymbols from collector which would throw an exception later on.
                    collector.WherePasses(new LogicalAndFilter(new List <ElementFilter>
                    {
                        new LogicalOrFilter(new List <ElementFilter>
                        {
                            new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting),
                            new ElementCategoryFilter(BuiltInCategory.OST_PipeAccessory),
                            new ElementClassFilter(typeof(Pipe))
                        }),
                        new LogicalOrFilter(new List <ElementFilter>
                        {
                            new ElementClassFilter(typeof(Pipe)),
                            new ElementClassFilter(typeof(FamilyInstance))
                        })
                    }));

                    colElements = collector.ToElements().ToHashSet();
                }

                else if (iv.ExportAllSepFiles || iv.ExportSpecificPipeLine)
                {
                    //Define a collector with multiple filters to collect PipeFittings OR PipeAccessories OR Pipes + filter by System Abbreviation
                    //System Abbreviation filter also filters FamilySymbols out.
                    collector.WherePasses(
                        new LogicalOrFilter(
                            new List <ElementFilter>
                    {
                        new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting),
                        new ElementCategoryFilter(BuiltInCategory.OST_PipeAccessory),
                        new ElementClassFilter(typeof(Pipe))
                    })).WherePasses(sysAbbr);
                    colElements = collector.ToElements().ToHashSet();
                }

                else if (iv.ExportSelection)
                {
                    //TODO: If selection is exported -- validate selected elements:
                    //Only fittings, accessories and pipes allowed -> everything else must be filtered out
                    ICollection <ElementId> selection = cData.Application.ActiveUIDocument.Selection.GetElementIds();
                    colElements = selection.Select(s => doc.GetElement(s)).ToHashSet();
                }

                //DiameterLimit filter applied to ALL elements.
                //Filter out EXCLuded elements - 0 means no checkmark, GUID is for PCF_ELEM_EXCL
                //Filter by system PCF_PIPL_EXCL: c1c2c9fe-2634-42ba-89d0-5af699f54d4c
                //PROBLEM: If user exports selection which includes element in a PipingSystem which is not allowed
                //PROBLEM: no elements will be exported
                //SOLUTION: Turn off PipingSystemAllowed filter off for ExportSelection case.
                HashSet <Element> elements = (from element in colElements
                                              where
                                              NTR_Filter.FilterDiameterLimit(element) &&
                                              element.get_Parameter(new Guid("CC8EC292-226C-4677-A32D-10B9736BFC1A")).AsInteger() == 0 &&
                                              element.PipingSystemAllowed(doc)
                                              select element).ToHashSet();

                //Add the elements from ARGD (Rigids) piping system back to working set
                //Which were filtered out by DiameterLimit, but still respecting PCF_ELEM_EXCL
                HashSet <Element> argdElemsOutsideDiaLimit =
                    colElements.Where(x => !NTR_Filter.FilterDiameterLimit(x) &&
                                      x.get_Parameter(new Guid("CC8EC292-226C-4677-A32D-10B9736BFC1A")).AsInteger() == 0 &&
                                      x.MEPSystemAbbreviation() == "ARGD").ToHashSet();

                //Combine the newly found ARGD elements back to main collection
                elements.UnionWith(argdElemsOutsideDiaLimit);

                //Create a grouping of elements based on the Pipeline identifier (System Abbreviation)
                pipelineGroups = from e in elements
                                 group e by e.get_Parameter(BuiltInParameter.RBS_DUCT_PIPE_SYSTEM_ABBREVIATION_PARAM).AsString();

                #endregion

                #region Configuration validation

                //Validate if configuration has all pipelines defined
                //Else no LAST value will be written!
                //PROBLEM: If user has pipelines which have been marked as not allowed and do not wish to define them
                //PROBLEM: in the configuration file, this validation will throw an error
                //SOLUTION: Exclude the names of not allowed PipingSystems from the list.
                List <string> pipeSysAbbrs = Shared.MepUtils.GetDistinctPhysicalPipingSystemTypeNames(doc).ToList();
                foreach (string sa in pipeSysAbbrs)
                {
                    string returnValue = DataWriter.ReadPropertyFromDataTable(sa, conf.Pipelines, "LAST");
                    if (returnValue.IsNullOrEmpty())
                    {
                        throw new Exception($"Pipeline {sa} is not defined in the configuration!");
                    }
                }


                #endregion

                outputBuilder.AppendLine("C Element definitions");

                #region Pipeline management

                //TransactionGroup to rollback the changes in creating the NonBreakInElements
                using (TransactionGroup txGp = new TransactionGroup(doc))
                {
                    txGp.Start("Olets non breakin elems.");

                    //List to store ALL created NonBreakInElements
                    //List<NonBreakInElement> nbifAllList = new List<NonBreakInElement>();

                    foreach (IGrouping <string, Element> gp in pipelineGroups)
                    {
                        HashSet <Element> pipeList = (from element in gp
                                                      where element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeCurves
                                                      select element).ToHashSet();
                        HashSet <Element> fittingList = (from element in gp
                                                         where element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeFitting
                                                         select element).ToHashSet();
                        HashSet <Element> accessoryList = (from element in gp
                                                           where element.Category.Id.IntegerValue == (int)BuiltInCategory.OST_PipeAccessory
                                                           select element).ToHashSet();

                        #region Olets and other non-break in items
                        //Here be code to handle non-breaking in elements as olets by the following principle:
                        //Find the non-breaking elements (fx. olets) and affected pipes.
                        //Remove affected pipes from pipeList and create in a transaction new, broken up pieces of pipe coinciding
                        //with olet and ends. Then add those pieces to the pipeList, !!!copy parameter values also!!! <- not needed for NTR?.
                        //Process pipeList as usual and then delete those new dummy pipes from model.

                        //TODO: Implement multiple types of non-breaking items per pipe -> only if needed -> cannot think of others than olets

                        //SpudAdjustable -> Olets
                        //Find fittings of this type:
                        IEnumerable <IGrouping <int, Element> > spudAdjQry = fittingList.Where(x => x.OfPartType(PartType.SpudAdjustable)).GroupBy(x => x.OletRefOwnerIdAsInt());

                        IList <NonBreakInElement> nbifList = new List <NonBreakInElement>();

                        foreach (IGrouping <int, Element> group in spudAdjQry)
                        {
                            nbifList.Add(new NonBreakInElement(doc, group));
                        }
                        //nbifAllList.AddRange(nbifList);

                        //Remove the HeadPipes from the PipeList
                        List <int> pipesToRemoveIds = nbifList.Select(x => x.HeadPipe.Id.IntegerValue).ToList();
                        pipeList = pipeList.ExceptWhere(x => pipesToRemoveIds.Contains(x.Id.IntegerValue)).ToHashSet();

                        //Transaction to create all part pipes
                        using (Transaction tx1 = new Transaction(doc))
                        {
                            tx1.Start("Create broken pipes.");

                            foreach (var g in nbifList)
                            {
                                for (int i = 0; i < g.AllCreationPoints.Count - 1; i++)
                                {
                                    int j = i + 1;
                                    g.CreatedElements.Add(Pipe.Create(doc, g.HeadPipe.MEPSystem.GetTypeId(), g.HeadPipe.GetTypeId(),
                                                                      g.HeadPipe.ReferenceLevel.Id, g.AllCreationPoints[i], g.AllCreationPoints[j]));
                                }

                                foreach (Element el in g.CreatedElements)
                                {
                                    el.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(g.HeadPipe.Diameter);
                                }

                                //Add created pipes to pipeList
                                pipeList.UnionWith(g.CreatedElements);
                            }

                            //Additional nodes need to be created for internal supports
                            //Internal supports need a separate master node for each support
                            if (iv.IncludeSteelStructure)
                            {
                                Guid tag4guid      = new Guid("f96a5688-8dbe-427d-aa62-f8744a6bc3ee");
                                var  SteelSupports = accessoryList.Where(
                                    x => x.get_Parameter(tag4guid).AsString() == "FRAME");

                                //Also modify accessoryList to remove the same said supports
                                accessoryList = accessoryList.ExceptWhere(
                                    x => x.get_Parameter(tag4guid).AsString() == "FRAME").ToHashSet();

                                foreach (FamilyInstance fi in SteelSupports)
                                {
                                    string familyName = fi.get_Parameter(BuiltInParameter.ELEM_FAMILY_PARAM).AsValueString();
                                    //Currently only the following family is implemented
                                    if (familyName == "VEKS bærering modplade")
                                    {
                                        Element elType     = doc.GetElement(fi.GetTypeId());
                                        bool    TopBool    = elType.LookupParameter("Modpl_Top_Vis").AsInteger() == 1;
                                        bool    BottomBool = elType.LookupParameter("Modpl_Bottom_Vis").AsInteger() == 1;
                                        bool    LeftBool   = elType.LookupParameter("Modpl_Left_Vis").AsInteger() == 1;
                                        bool    RightBool  = elType.LookupParameter("Modpl_Right_Vis").AsInteger() == 1;

                                        //Count how many extra nodes are needed
                                        int extraNodeCount = 0;
                                        if (TopBool)
                                        {
                                            extraNodeCount++;
                                        }
                                        if (BottomBool)
                                        {
                                            extraNodeCount++;
                                        }
                                        if (LeftBool)
                                        {
                                            extraNodeCount++;
                                        }
                                        if (RightBool)
                                        {
                                            extraNodeCount++;
                                        }

                                        if (extraNodeCount == 0)
                                        {
                                            continue;
                                        }
                                        else if (extraNodeCount == 1)
                                        {
                                            continue;
                                        }

                                        Cons supportCons = new Cons((Element)fi);

                                        //Getting the corresponding connectors with AllRefs method cannot be used
                                        //Because if two supports reside on same pipe
                                        //Subsequent iterations will get the original pipe, which will make overlapping segments
                                        //So connectors must be obtained by matching geometry
                                        //And it must be done separately at each iteration!

                                        var allConnectors = MepUtils.GetALLConnectorsFromElements(pipeList)
                                                            .Where(c => c.ConnectorType == ConnectorType.End).ToHashSet();

                                        var matchedPipeConnectors = allConnectors
                                                                    .Where(x => supportCons.Primary.Equalz(x, 1.0.MmToFt()))
                                                                    .ExceptWhere(x => x.Owner.Id.IntegerValue == fi.Id.IntegerValue);

                                        //Should be a null check here -> to tired to figure it out
                                        Connector FirstSideConStart = matchedPipeConnectors.First();

                                        //Assume that supports will always be placed on pipes
                                        Connector FirstSideConEnd =
                                            (from Connector c in FirstSideConStart.ConnectorManager.Connectors
                                             where c.Id != FirstSideConStart.Id && (int)c.ConnectorType == 1
                                             select c).FirstOrDefault();

                                        Connector SecondSideConStart = matchedPipeConnectors.Last();

                                        //Assume that supports will always be placed on pipes
                                        Connector SecondSideConEnd =
                                            (from Connector c in SecondSideConStart.ConnectorManager.Connectors
                                             where c.Id != SecondSideConStart.Id && (int)c.ConnectorType == 1
                                             select c).FirstOrDefault();

                                        //Create help lines to help with the geometry analysis
                                        //The point is to get a point along the line at 5 mm distance from start
                                        Line FirstSideLine  = Line.CreateBound(FirstSideConStart.Origin, FirstSideConEnd.Origin);
                                        Line SecondSideLine = Line.CreateBound(SecondSideConStart.Origin, SecondSideConEnd.Origin);

                                        List <XYZ> creationPoints = new List <XYZ>(extraNodeCount + 2);

                                        if (extraNodeCount == 2)
                                        {
                                            creationPoints.Add(FirstSideConEnd.Origin);
                                            creationPoints.Add(FirstSideLine.Evaluate(2.5.MmToFt(), false));
                                            creationPoints.Add(SecondSideLine.Evaluate(2.5.MmToFt(), false));
                                            creationPoints.Add(SecondSideConEnd.Origin);
                                        }

                                        else if (extraNodeCount == 3)
                                        {
                                            creationPoints.Add(FirstSideConEnd.Origin);
                                            creationPoints.Add(FirstSideLine.Evaluate(5.0.MmToFt(), false));
                                            creationPoints.Add(FirstSideConStart.Origin);
                                            creationPoints.Add(SecondSideLine.Evaluate(5.0.MmToFt(), false));
                                            creationPoints.Add(SecondSideConEnd.Origin);
                                            //Dbg.PlaceAdaptiveFamilyInstance(doc, "Marker Line: Red", FirstSideConStart.Origin, FirstSidePoint);
                                            //Dbg.PlaceAdaptiveFamilyInstance(doc, "Marker Line: Red", SecondSideConStart.Origin, SecondSidePoint);
                                        }

                                        else if (extraNodeCount == 4)
                                        {
                                            creationPoints.Add(FirstSideConEnd.Origin);
                                            creationPoints.Add(FirstSideLine.Evaluate(7.5.MmToFt(), false));
                                            creationPoints.Add(FirstSideLine.Evaluate(2.5.MmToFt(), false));
                                            creationPoints.Add(SecondSideLine.Evaluate(2.5.MmToFt(), false));
                                            creationPoints.Add(SecondSideLine.Evaluate(7.5.MmToFt(), false));
                                            creationPoints.Add(SecondSideConEnd.Origin);
                                        }

                                        //Remove the original pipes from pipeList
                                        Pipe fPipe = (Pipe)FirstSideConStart.Owner;
                                        Pipe sPipe = (Pipe)SecondSideConStart.Owner;
                                        pipeList = pipeList.ExceptWhere(x => x.Id.IntegerValue == fPipe.Id.IntegerValue)
                                                   .ExceptWhere(x => x.Id.IntegerValue == sPipe.Id.IntegerValue)
                                                   .ToHashSet();

                                        //Create extra pipes
                                        HashSet <Element> createdPipes = new HashSet <Element>();
                                        for (int i = 0; i < creationPoints.Count - 1; i++)
                                        {
                                            int j = i + 1;
                                            createdPipes.Add(Pipe.Create(doc, fPipe.MEPSystem.GetTypeId(), fPipe.GetTypeId(),
                                                                         fPipe.ReferenceLevel.Id, creationPoints[i], creationPoints[j]));
                                        }

                                        foreach (Element el in createdPipes)
                                        {
                                            el.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(fPipe.Diameter);
                                        }

                                        //Add created pipes to pipeList
                                        pipeList.UnionWith(createdPipes);
                                    }
                                    else
                                    {
                                    }       //Implement other possibilities later

                                    //This, I think, is needed to be able to interact with temporary pipes
                                    doc.Regenerate();
                                }
                            }

                            tx1.Commit();
                        }

                        #endregion

                        //TODO: Change the splitting of elements to follow the worksheets
                        //There's now a mismatch of how many worksheets define the elements (ELEMENTS and SUPPORTS) and
                        //the division into fittings and accessories. Would be more concise to follow the excel configuration
                        //by worksheet

                        StringBuilder sbPipes       = NTR_Pipes.Export(gp.Key, pipeList, conf, doc);
                        StringBuilder sbFittings    = NTR_Fittings.Export(gp.Key, fittingList, conf, doc);
                        StringBuilder sbAccessories = NTR_Accessories.Export(gp.Key, accessoryList, conf, doc);

                        outputBuilder.Append(sbPipes);
                        outputBuilder.Append(sbFittings);
                        outputBuilder.Append(sbAccessories);
                    }

                    //Include steel structure here
                    //Requires that the Support Pipe Accessories which the structure support are filtered in the above section
                    if (iv.IncludeSteelStructure)
                    {
                        StringBuilder sbSteel = new NTR_Steel(doc).ExportSteel();
                        outputBuilder.Append(sbSteel);

                        StringBuilder sbBoundaryConds = new NTR_Steel(doc).ExportBoundaryConditions();
                        outputBuilder.Append(sbBoundaryConds);
                    }

                    #region Debug
                    //string ids = string.Empty;
                    //foreach (var g in nbifAllList) foreach (var e in g.CreatedElements) ids += e.Id.ToString() + "\n";
                    //BuildingCoderUtilities.InfoMsg(ids);
                    #endregion

                    txGp.RollBack(); //Rollback the extra elements created
                    //txGp.Commit(); //For debug purposes can be uncommented
                }
                #endregion

                #region Hangers
                //Temporary section to handle GenericModel hangers
                //Works only if all line in one file selected

                //outputBuilder.Append(NTR_GenericModels.ExportHangers(conf, doc));
                #endregion


                #region Output
                // Output the processed data
                NTR_Output.Output output = new NTR_Output.Output();
                output.OutputWriter(doc, outputBuilder, iv.OutputDirectoryFilePath);
                #endregion
            }

            catch (Autodesk.Revit.Exceptions.OperationCanceledException)
            {
                return(Result.Cancelled);
            }

            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return(Result.Succeeded);
        }
Esempio n. 17
0
        internal Result ExecuteMyCommand(UIApplication uiApp, ref string msg)
        {
            Document doc = uiApp.ActiveUIDocument.Document;

            try
            {
                #region Declaration of variables
                // Instance a collector
                FilteredElementCollector collector = new FilteredElementCollector(doc);

                // Define a Filter instance to filter by System Abbreviation
                ElementParameterFilter sysAbbr = Shared.Filter.ParameterValueGenericFilter(doc, InputVars.SysAbbr, InputVars.SysAbbrParam);

                // Declare pipeline grouping object
                IEnumerable <IGrouping <string, Element> > pipelineGroups;

                //Declare an object to hold collected elements from collector
                HashSet <Element> colElements = new HashSet <Element>();

                //Declare an object to hold filtered elements
                HashSet <Element> filteredElements = new HashSet <Element>();

                // Instance a collecting stringbuilder
                StringBuilder sbCollect = new StringBuilder();
                #endregion


                #region Element collectors
                //If user chooses to export a single pipeline get only elements in that pipeline and create grouping.
                //Grouping is necessary even tho theres only one group to be able to process by the same code as the all pipelines case

                //If user chooses to export all pipelines get all elements and create grouping
                if (InputVars.ExportAllOneFile)
                {
                    //Define a collector (Pipe OR FamInst) AND (Fitting OR Accessory OR Pipe).
                    //This is to eliminate FamilySymbols from collector which would throw an exception later on.
                    collector.WherePasses(new LogicalAndFilter(new List <ElementFilter>
                    {
                        new LogicalOrFilter(new List <ElementFilter>
                        {
                            new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting),
                            new ElementCategoryFilter(BuiltInCategory.OST_PipeAccessory),
                            new ElementClassFilter(typeof(Pipe))
                        }),
                        new LogicalOrFilter(new List <ElementFilter>
                        {
                            new ElementClassFilter(typeof(Pipe)),
                            new ElementClassFilter(typeof(FamilyInstance))
                        })
                    }));

                    colElements = collector.ToElements().ToHashSet();
                }

                else if (InputVars.ExportAllSepFiles || InputVars.ExportSpecificPipeLine)
                {
                    //Define a collector with multiple filters to collect PipeFittings OR PipeAccessories OR Pipes + filter by System Abbreviation
                    //System Abbreviation filter also filters FamilySymbols out.
                    collector.WherePasses(
                        new LogicalOrFilter(
                            new List <ElementFilter>
                    {
                        new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting),
                        new ElementCategoryFilter(BuiltInCategory.OST_PipeAccessory),
                        new ElementClassFilter(typeof(Pipe))
                    })).WherePasses(sysAbbr);
                    colElements = collector.ToElements().ToHashSet();
                }

                else if (InputVars.ExportSelection)
                {
                    ICollection <ElementId> selection = uiApp.ActiveUIDocument.Selection.GetElementIds();
                    colElements = selection.Select(s => doc.GetElement(s)).ToHashSet();
                }

                try
                {
                    //DiameterLimit filter applied to ALL elements.
                    filteredElements = (from element in colElements
                                        where
                                        //Diameter limit filter
                                        FilterDiameterLimit.FilterDL(element) &&
                                        ////Filter out elements with empty PCF_ELEM_TYPE field (remember to !negate)
                                        //!string.IsNullOrEmpty(element.get_Parameter(new plst().PCF_ELEM_TYPE.Guid).AsString()) &&
                                        //Filter out EXCLUDED elements -> 0 means no checkmark
                                        element.get_Parameter(new plst().CII_ELEM_EXCL.Guid).AsInteger() == 0 &&
                                        //Filter out caps -- they are ignored... for now...
                                        !MepUtils.IsTheElementACap(element)
                                        select element).ToHashSet();

                    //Create a grouping of elements based on the Pipeline identifier (System Abbreviation)
                    pipelineGroups = from e in filteredElements
                                     group e by e.LookupParameter(InputVars.PipelineGroupParameterName).AsString();
                }
                catch (Exception ex)
                {
                    throw new Exception("Filtering in Main threw an exception:\n" + ex.Message +
                                        "\nTo fix:\n" +
                                        "1. See if parameter CII_ELEM_EXCL exists, if not, rerun parameter import.");
                }

                #endregion

                #region Analysis

                MEPSystemTraversal MST = new MEPSystemTraversal(doc, filteredElements);
                MST.AnalyzeSystem();
                MST.NumberNodes();
                //MST.PlaceTextNotesAtNodes();

                #endregion

                #region Data Processing
                ModelData Data = new ModelData(MST.Model);
                Data.ProcessData();

                #endregion

                #region Output
                // Output the processed data

                sbCollect.Append(Data._01_VERSION);
                sbCollect.Append(Data._02_CONTROL);
                sbCollect.Append(Data._03_ELEMENTS);
                sbCollect.Append(Data._04_AUXDATA);
                if (Data._05_NODENAME != null)
                {
                    sbCollect.Append(Data._05_NODENAME);
                }
                sbCollect.Append(Data._06_BEND);
                sbCollect.Append(Data._07_RIGID);
                sbCollect.Append(Data._08_EXPJT);
                sbCollect.Append(Data._09_RESTRANT);
                sbCollect.Append(Data._10_DISPLMNT);
                sbCollect.Append(Data._11_FORCMNT);
                sbCollect.Append(Data._12_UNIFORM);
                sbCollect.Append(Data._13_WIND);
                sbCollect.Append(Data._14_OFFSETS);
                sbCollect.Append(Data._15_ALLOWBLS);
                sbCollect.Append(Data._16_SIFTEES);
                sbCollect.Append(Data._17_REDUCERS);
                sbCollect.Append(Data._18_FLANGES);
                sbCollect.Append(Data._19_EQUIPMNT);
                sbCollect.Append(Data._20_MISCEL_1);
                sbCollect.Append(Data._21_UNITS);
                sbCollect.Append(Data._22_COORDS);

                Output output = new Output();
                output.OutputWriter(doc, sbCollect, InputVars.OutputDirectoryFilePath);
                #endregion
            }

            catch (Autodesk.Revit.Exceptions.OperationCanceledException)
            {
                return(Result.Cancelled);
            }

            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return(Result.Succeeded);
        }
Esempio n. 18
0
        public static void ConnectTheConnectors(ExternalCommandData commandData)
        {
            try
            {
                bool ctrl = false;
                bool shft = false;
                if ((int)Keyboard.Modifiers == 2)
                {
                    ctrl = true;
                }
                if ((int)Keyboard.Modifiers == 4)
                {
                    shft = true;
                }

                var app       = commandData.Application;
                var uiDoc     = app.ActiveUIDocument;
                var doc       = uiDoc.Document;
                var selection = uiDoc.Selection.GetElementIds();

                //If no elements selected, connect ALL connectors to ALL connectors
                //Or if more than two -- connect to each other
                if ((selection.Count == 0 || selection.Count > 2) && !ctrl)
                {
                    //Argh! It seems Revit2019 doesn't break when connecting pipes at angle!!!
                    ////To filter out PCF_ELEM_EXCL set to true
                    ////Collecting pipes, fittings, accessories
                    ////Filtering out those with "true" value
                    ////The Guid below is for PCF_ELEM_EXCL
                    //var exclFilter = fi.ParameterValueGenericFilter(doc, 0, new Guid("CC8EC292-226C-4677-A32D-10B9736BFC1A"));

                    //FilteredElementCollector col1 = new FilteredElementCollector(doc);
                    //col1.WherePasses(
                    //        new LogicalOrFilter(
                    //            new List<ElementFilter>
                    //            {
                    //                new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting),
                    //                new ElementCategoryFilter(BuiltInCategory.OST_PipeAccessory),
                    //                new ElementClassFilter(typeof (Pipe))
                    //            }));//.WherePasses(exclFilter);
                    //var col2 = mp.GetElementsOfBuiltInCategory(doc, BuiltInCategory.OST_MechanicalEquipment);

                    //HashSet<Element> elements = new HashSet<Element>();
                    //elements.UnionWith(col1);
                    //elements.UnionWith(col2);

                    //When selection is 0
                    IList <Connector> allConnectors;
                    if (selection.Count == 0)
                    {
                        allConnectors = mp.GetALLConnectorsInDocument(doc, true)
                                        .Where(c => !c.IsConnected)
                                        .ExceptWhere(c => c.MEPSystemAbbreviation(doc, true) == "ARGD")
                                        .ToList();
                    }
                    //Selection is more than 2
                    else
                    {
                        allConnectors = mp.GetALLConnectorsFromElements((from ElementId id in selection select doc.GetElement(id)).ToHashSet()).ToList();
                    }


                    //Employ reverse iteration to be able to modify the collection while iterating over it
                    for (int i = allConnectors.Count - 1; i > 0; i--)
                    {
                        if (allConnectors.Count < 2)
                        {
                            break;
                        }
                        Connector c1 = allConnectors[i];
                        allConnectors.RemoveAt(i);
                        if (c1.IsConnected)
                        {
                            continue;                 //Need: connectors connected in this loop are still in collection
                        }
                        Connector c2 = (from Connector c in allConnectors where c.Equalz(c1, Extensions._1mmTol) select c).FirstOrDefault();
                        try
                        {
                            if (c1?.Owner.Id.IntegerValue == c2?.Owner.Id.IntegerValue)
                            {
                                continue;
                            }
                            c2?.ConnectTo(c1);
                        }
                        catch (Exception)
                        {
                            throw new Exception($"Element {c1.Owner.Id.ToString()} is already connected to element {c2.Owner.Id.ToString()}");
                        }
                    }

                    return;
                }

                else if (selection.Count == 1 && shft)
                {
                    ElementId hangerId = selection.First();
                    Element   hanger   = doc.GetElement(hangerId);
                    Cons      cons     = new Cons(hanger);

                    var allConnectors = mp.GetALLConnectorsInDocument(doc).ToList();

                    var query = allConnectors.Where(c => c.Equalz(cons.Primary, Extensions._1mmTol)).Where(c => c.Owner.Id.IntegerValue != hanger.Id.IntegerValue).ToList();

                    //Disconnect connectors of the existing components if the hanger was moved in place
                    Connector con1 = query.FirstOrDefault();
                    if (con1 == null)
                    {
                        throw new Exception("Detection of existing con1 failed!");
                    }
                    Connector con2 = query.LastOrDefault();
                    if (con2 == null)
                    {
                        throw new Exception("Detection of existing con2 failed!");
                    }

                    if (con1.IsConnectedTo(con2))
                    {
                        con1.DisconnectFrom(con2);
                    }

                    //If the hanger was created by placing on element and thus auto connected -> disconnect both connectors
                    //Dunno if this is needed and placing by auto connect does orient the connectors correctly
                    //Until it is proven true, both connectors are disconnected
                    if (cons.Primary.IsConnected)
                    {
                        var refCons = cons.Primary.AllRefs;
                        var refCon  = MepUtils.GetAllConnectorsFromConnectorSet(refCons)
                                      .Where(c => c.Owner.IsType <Pipe>() || c.Owner.IsType <FamilyInstance>()).FirstOrDefault();
                        if (refCon != null)
                        {
                            cons.Primary.DisconnectFrom(refCon);
                        }
                    }
                    if (cons.Secondary.IsConnected)
                    {
                        var refCons = cons.Secondary.AllRefs;
                        var refCon  = MepUtils.GetAllConnectorsFromConnectorSet(refCons)
                                      .Where(c => c.Owner.IsType <Pipe>() || c.Owner.IsType <FamilyInstance>()).FirstOrDefault();
                        if (refCon != null)
                        {
                            cons.Primary.DisconnectFrom(refCon);
                        }
                    }
                    doc.Regenerate();

                    //Start connecting hanger connectors
                    //https://stackoverflow.com/questions/7572640/how-do-i-know-if-two-vectors-are-near-parallel
                    var       detectOpposite1 = query.Where(c => cons.Primary.CoordinateSystem.BasisZ.DotProduct(c.CoordinateSystem.BasisZ) < -1 + Extensions._epx);
                    Connector opposite1       = detectOpposite1.FirstOrDefault();
                    if (opposite1 == null)
                    {
                        throw new Exception("Opposite primary detection failed!");
                    }
                    cons.Primary.ConnectTo(opposite1);

                    var       detectOpposite2 = query.Where(c => cons.Secondary.CoordinateSystem.BasisZ.DotProduct(c.CoordinateSystem.BasisZ) < -1 + Extensions._epx);
                    Connector opposite2       = detectOpposite2.FirstOrDefault();
                    if (opposite2 == null)
                    {
                        throw new Exception("Opposite secondary detection failed!");
                    }
                    cons.Secondary.ConnectTo(opposite2);

                    return;
                }

                else if (selection.Count == 1 && !ctrl) //If one and no CTRL key, connect the element
                {
                    var elements          = new HashSet <Element>(from ElementId id in selection select doc.GetElement(id));
                    var elementConnectors = mp.GetALLConnectorsFromElements(elements);
                    var allConnectors     = mp.GetALLConnectorsInDocument(doc, true).Where(c => !c.IsConnected).ToList();

                    IList <Connector> list1 = new List <Connector>();
                    IList <Connector> list2 = new List <Connector>();

                    foreach (var c1 in elementConnectors)
                    {
                        foreach (var c2 in allConnectors)
                        {
                            if (c1.Id != c2.Id && !c1.IsConnected && c1.Equalz(c2, Extensions._1mmTol))
                            {
                                list1.Add(c1);
                                list2.Add(c2);
                            }
                        }
                    }

                    if (list1.Count == 0 && list2.Count == 0)
                    {
                        throw new Exception("No matches found! Check alignment!");
                    }

                    foreach (var(c1, c2) in list1.Zip(list2, (x, y) => (c1: x, c2: y)))
                    {
                        c1.ConnectTo(c2);
                    }

                    return;
                }

                else if ((selection.Count == 1 || selection.Count > 2) && ctrl) //If one and CTRL key is pressed, disconnect the element
                {
                    var elements          = new HashSet <Element>(from ElementId id in selection select doc.GetElement(id));
                    var elementConnectors = mp.GetALLConnectorsFromElements(elements);

                    foreach (Connector c1 in elementConnectors)
                    {
                        if (c1.IsConnected)
                        {
                            var set = c1.AllRefs;
                            foreach (Connector c2 in set)
                            {
                                if (c1.IsConnectedTo(c2))
                                {
                                    c1.DisconnectFrom(c2);
                                }
                            }
                        }
                    }

                    return;
                }

                //Connect or disconnect the connectors of selection
                //Only works on selection of two adjacent elements
                //That means only two connectors get connected to or disconnected from each other
                else if (selection.Count == 2)
                {
                    var elements   = new HashSet <Element>(from ElementId id in selection select doc.GetElement(id));
                    var connectors = mp.GetALLConnectorsFromElements(elements).ToList();

                    for (int i = connectors.Count - 1; i > 0; i--)
                    {
                        if (connectors.Count < 2)
                        {
                            throw new Exception("No eligible connectors found! Check alignment.");
                        }
                        Connector c1 = connectors[i];
                        connectors.RemoveAt(i);
                        Connector c2 = (from Connector c in connectors where c.Equalz(c1, Extensions._1mmTol) select c).FirstOrDefault();
                        if (c2 != null)
                        {
                            if (c1.Owner.Id.IntegerValue == c2.Owner.Id.IntegerValue)
                            {
                                continue;
                            }
                            if (c1.IsConnected)
                            {
                                c2.DisconnectFrom(c1);
                            }
                            else
                            {
                                c2.ConnectTo(c1);
                            }
                        }
                    }

                    return;
                }
                else
                {
                    throw new Exception("Not correct amount of elements selected for the command! Choose none, one or two!");
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }