/// <summary>
        /// Adds a sectional connected to an element
        /// </summary>
        /// <param name="elm"></param>
        /// <returns></returns>
        public MEPRevitNode NewSection(Element elm, gmdl.MEPEdgeTypes edgeType)
        {
            var sectionNode = new MEPRevitNode("Generic");

            if (elm != null)
            {
                var intNode = AddElement(elm);
                var cl      = AddConnection(sectionNode, intNode, MEPPathConnectionType.SectionOf, edgeType);
            }

            return(sectionNode);
        }
        /// <summary>
        /// Add a connection between two nodes
        /// </summary>
        /// <param name="fromNode"></param>
        /// <param name="toNode"></param>
        /// <param name="connectionType"></param>
        /// <param name="edgeType"></param>
        /// <returns></returns>
        public MEPRevitEdge AddConnection(MEPRevitNode fromNode, MEPRevitNode toNode, MEPPathConnectionType connectionType, gmdl.MEPEdgeTypes edgeType)
        {
            AddNode(fromNode);
            AddNode(toNode);

            var cnEdge = fromNode.Connections.FirstOrDefault(cn => cn.ConnectionType == connectionType && cn.AsNodeEdge.EdgeType == edgeType && cn.NextNode == toNode);

            if (cnEdge == null)
            {
                cnEdge = toNode.Connections.FirstOrDefault(cn => cn.ConnectionType == connectionType && cn.AsNodeEdge.EdgeType == edgeType && cn.NextNode == fromNode);
            }

            if (cnEdge == null)
            {
                cnEdge = new MEPRevitEdge(toNode.OriginId, fromNode, toNode, MEPPathDirection.In);
                _edges.Add(cnEdge);
                cnEdge.ConnectionType      = connectionType;
                cnEdge.AsNodeEdge.EdgeType = edgeType;
                cnEdge.SystemId            = -1;
                fromNode.Connections.Add(cnEdge);
                toNode.Connections.Add(cnEdge);
            }

            return(cnEdge);
        }
        /// <summary>
        /// Connect two connectors together
        /// </summary>
        /// <param name="conn1"></param>
        /// <param name="conn2"></param>
        /// <param name="connectionType"></param>
        /// <returns></returns>
        public MEPRevitEdge AddConnection(Connector conn1, Connector conn2, MEPPathConnectionType connectionType, gmdl.MEPEdgeTypes edgeType)
        {
            //direction should always be conn1 IN_TO conn2
            if ((conn1.Domain == Autodesk.Revit.DB.Domain.DomainPiping || conn1.Domain == Autodesk.Revit.DB.Domain.DomainHvac) && conn1.Direction == FlowDirectionType.In)
            {
                //swap over references
                var tempConn1 = conn1;
                conn1 = conn2;
                conn2 = tempConn1;
            }



            MEPRevitNode conn1Node = AddElement(conn1.Owner);
            MEPRevitNode conn2Node = AddElement(conn2.Owner);

            MEPRevitEdge connEdge = null;

#if REVIT2016
            connEdge = conn1Node.Connections.FirstOrDefault(ed =>
                                                            ed.ConnectionType == connectionType &&
                                                            ed.ThisConnectorIndex == conn1.Id &&
                                                            ed.NextNode == conn2Node &&
                                                            ed.NextConnectorIndex == conn2.Id);
#else
            throw new Exception("Only supported in Revit 2016 onwards");
#endif

            if (connEdge == null)
            {
#if REVIT2016
                connEdge = conn2Node.Connections.FirstOrDefault(ed =>
                                                                ed.ConnectionType == connectionType &&
                                                                ed.ThisConnectorIndex == conn2.Id &&
                                                                ed.NextNode == conn1Node &&
                                                                ed.NextConnectorIndex == conn1.Id);
#endif
            }

            if (connEdge == null)
            {
#if REVIT2016
                connEdge = new MEPConnectorNodeEdge(conn1.Id, conn1Node, conn2Node, conn1.Domain == Autodesk.Revit.DB.Domain.DomainHvac || conn1.Domain == Autodesk.Revit.DB.Domain.DomainPiping ? (MEPPathDirection)(int)conn1.Direction : MEPPathDirection.Indeterminate);
                _edges.Add(connEdge);
#else
                throw new Exception("Only supported in Revit 2016 onwards");
#endif
                conn1Node.Connections.Add(connEdge);
                conn2Node.Connections.Add(connEdge);
                connEdge.ThisConnectorIndex = conn1.Id;
                connEdge.NextConnectorIndex = conn2.Id;
                connEdge.ThisOrigin         = conn1.Origin;
                connEdge.NextOrigin         = conn2.Origin;
                connEdge.NextNode           = conn2Node;
            }

            var ow = conn1.Owner;
            if (ow != null)
            {
                var scp = ow.get_Parameter(BuiltInParameter.RBS_SYSTEM_CLASSIFICATION_PARAM);
                var sct = ow.get_Parameter(BuiltInParameter.RBS_DUCT_SYSTEM_TYPE_PARAM);
                var scn = ow.get_Parameter(BuiltInParameter.RBS_SYSTEM_NAME_PARAM);

                if (scp != null)
                {
                    connEdge.SetWeight("System Classification", scp.AsString());
                }
                if (sct != null)
                {
                    var st = sct.AsValueString();
                    connEdge.SetWeight("System Type", st);
                    if (!string.IsNullOrEmpty(st))
                    {
                        connEdge.AsNodeEdge.TypeLabel = "FL_" + st.ToUpper().Replace(" ", "_");
                    }
                }

                if (scn != null)
                {
                    connEdge.SetWeight("System Name", scn.AsString());
                }
            }


            connEdge.ConnectionType = connectionType;
            connEdge.SystemId       = conn1.MEPSystem != null ? conn1.MEPSystem.Id.IntegerValue : -1;
            connEdge.Description    = conn1.Description;
            //connEdge.Length = MEPGraphParserConnectors.GetDistanceBetweenConnectors(conn1, conn2);
            connEdge.AsNodeEdge.EdgeType = edgeType;


            if (conn1.Domain == Autodesk.Revit.DB.Domain.DomainHvac || conn1.Domain == Autodesk.Revit.DB.Domain.DomainPiping)
            {
                connEdge.Flow = conn1.Flow;
            }


            if (conn1.MEPSystem != null && !Systems.Contains(conn1.MEPSystem.Id.IntegerValue))
            {
                Systems.Add(conn1.MEPSystem.Id.IntegerValue);
            }

            if (conn2.MEPSystem != null && !Systems.Contains(conn2.MEPSystem.Id.IntegerValue))
            {
                Systems.Add(conn2.MEPSystem.Id.IntegerValue);
            }

            if (conn1.MEPSystem != null)
            {
                connEdge.SetWeight("SystemName", conn1.MEPSystem.Name);
            }
            else if (conn2.MEPSystem != null)
            {
                connEdge.SetWeight("SystemName", conn2.MEPSystem.Name);
            }

            return(connEdge);
        }
        /// <summary>
        /// Adds a connection between a connector and a point on or in another element
        /// </summary>
        /// <param name="conn1"></param>
        /// <param name="otherPoint"></param>
        /// <param name="otherElement"></param>
        /// <param name="connectionType"></param>
        /// <returns></returns>
        public MEPRevitEdge AddConnection(Connector conn1, XYZ otherPoint, Element otherElement, MEPPathConnectionType connectionType, gmdl.MEPEdgeTypes edgeType)
        {
            //create nodes for the two elements
            var conn1Node = AddElement(conn1.Owner);
            var conn2Node = AddElement(otherElement);

            var edges = GetEdges(conn1);

            //look for an edge which already exists
            MEPRevitEdge connEdge = null;

#if REVIT2016
            connEdge = conn1Node.Connections.FirstOrDefault(ed =>
                                                            ed.ThisConnectorIndex == conn1.Id &&
                                                            ed.ConnectionType == connectionType &&
                                                            ed.AsNodeEdge.EdgeType == edgeType &&
                                                            ed.NextOrigin.DistanceTo(otherPoint) < 0.01);
#else
            throw new Exception("Only supported in Revit 2016 onwards");
#endif


            //direction should always be conn1 IN_TO conn2
            if (conn1.Direction == FlowDirectionType.In)
            {
                //swap over references
                var tempconn1Node = conn1Node;
                conn1Node = conn2Node;
                conn2Node = tempconn1Node;
            }

            //create edge if an existing one wasn't found
            if (connEdge == null)
            {
#if REVIT2016
                connEdge = new MEPRevitEdge(conn1.Id, conn1Node, conn2Node,
                                            conn1.Domain == Autodesk.Revit.DB.Domain.DomainHvac ||
                                            conn1.Domain == Autodesk.Revit.DB.Domain.DomainPiping ? (MEPPathDirection)(int)conn1.Direction : MEPPathDirection.Indeterminate);
                connEdge.ConnectionType      = connectionType;
                connEdge.AsNodeEdge.EdgeType = edgeType;
                _edges.Add(connEdge);
#else
                throw new Exception("Only supported in Revit 2016 onwards");
#endif
                conn1Node.Connections.Add(connEdge);
                conn2Node.Connections.Add(connEdge);
            }


            connEdge.NextNode            = conn2Node;
            connEdge.ConnectionType      = connectionType;
            connEdge.SystemId            = conn1.MEPSystem != null ? conn1.MEPSystem.Id.IntegerValue : -1;
            connEdge.ThisOrigin          = conn1.Origin;
            connEdge.Description         = conn1.Description;
            connEdge.AsNodeEdge.EdgeType = edgeType;
            if (conn1.Domain == Autodesk.Revit.DB.Domain.DomainHvac || conn1.Domain == Autodesk.Revit.DB.Domain.DomainPiping)
            {
                connEdge.Weights.Add("Flow", conn1.Flow);
            }
            // if (conn1.Domain == Autodesk.Revit.DB.Domain.DomainElectrical) connEdge.Weights.Add("Load", conn1.);

            MEPSystem system = null;
            if (otherElement is MEPCurve)
            {
                system = (otherElement as MEPCurve).MEPSystem;
            }
            else if (otherElement is FamilyInstance)
            {
                var famInstElm = (otherElement as FamilyInstance);
                if (famInstElm.MEPModel != null && famInstElm.MEPModel.ConnectorManager != null)
                {
                    //just get the system from the first connector with valid system
                    var systemConn = famInstElm.MEPModel.ConnectorManager.Connectors.OfType <Connector>().FirstOrDefault(cn => cn.MEPSystem != null);
                    if (systemConn != null)
                    {
                        system = systemConn.MEPSystem;
                    }
                }
            }


            if (conn1.MEPSystem != null && !Systems.Contains(conn1.MEPSystem.Id.IntegerValue))
            {
                Systems.Add(conn1.MEPSystem.Id.IntegerValue);
            }

            if (system != null && !Systems.Contains(system.Id.IntegerValue))
            {
                Systems.Add(system.Id.IntegerValue);
            }



            return(connEdge);
        }
        /// <summary>
        /// Adds a connection between two elements
        /// </summary>
        /// <param name="fromElement"></param>
        /// <param name="otherElement"></param>
        /// <param name="edgeType"></param>
        /// <returns></returns>
        public MEPRevitEdge AddConnection(Element fromElement, Element otherElement, MEPPathConnectionType connectionType, gmdl.MEPEdgeTypes edgeType)
        {
            var conn1Node = AddElement(fromElement);
            var conn2Node = AddElement(otherElement);
            var connEdge  = AddConnection(conn1Node, conn2Node, connectionType, edgeType);

            return(connEdge);
        }
        /// <summary>
        /// Adds a connection between two elements at specific point
        /// </summary>
        /// <param name="fromElement"></param>
        /// <param name="otherElement"></param>
        /// <param name="atPoint"></param>
        /// <param name="connectionType"></param>
        /// <param name="edgeType"></param>
        /// <returns></returns>
        public MEPRevitEdge AddConnection(Element fromElement, Element otherElement, XYZ atPoint, MEPPathConnectionType connectionType, gmdl.MEPEdgeTypes edgeType)
        {
            var edge = AddConnection(fromElement, otherElement, connectionType, edgeType);

            edge.NextOrigin = atPoint;
            edge.ThisOrigin = atPoint;

            return(edge);
        }