static void AddConnection(ExporterIFC exporterIFC, Connector connector, Connector connected, bool isBiDirectional, bool isElectricalDomain) { // Port connection is not allowed in IFC4RV MVD if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { return; } Element inElement = connector.Owner; Element outElement = connected.Owner; if (isElectricalDomain) { // We may get a connection back to the original element. Ignore it. if (inElement.Id == outElement.Id) { return; } // Check the outElement to see if it is a Wire; if so, get its connections and "skip" the wire. if (outElement is Wire) { if (m_ProcessedWires.Contains(outElement.Id)) { return; } m_ProcessedWires.Add(outElement.Id); try { ConnectorSet wireConnectorSet = MEPCache.GetConnectorsForWire(outElement as Wire); if (wireConnectorSet != null) { foreach (Connector connectedToWire in wireConnectorSet) { ProcessConnections(exporterIFC, connectedToWire, connector); } } } catch { } return; } } // Check if the connection already exist if (ConnectionExists(inElement.Id, outElement.Id)) { return; } if (isBiDirectional) { if (ConnectionExists(outElement.Id, inElement.Id)) { return; } } IFCAnyHandle inElementIFCHandle = ExporterCacheManager.MEPCache.Find(inElement.Id); IFCAnyHandle outElementIFCHandle = ExporterCacheManager.MEPCache.Find(outElement.Id); // Note TBD: In IFC4 the IfcRelConnectsPortToElement should be used for a dynamic connection. THe static connection should use IfcRelNests if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { if (inElementIFCHandle == null || outElementIFCHandle == null || !IFCAnyHandleUtil.IsSubTypeOf(inElementIFCHandle, IFCEntityType.IfcDistributionElement) || !IFCAnyHandleUtil.IsSubTypeOf(outElementIFCHandle, IFCEntityType.IfcDistributionElement)) { return; } } else { if (inElementIFCHandle == null || outElementIFCHandle == null || !IFCAnyHandleUtil.IsSubTypeOf(inElementIFCHandle, IFCEntityType.IfcElement) || !IFCAnyHandleUtil.IsSubTypeOf(outElementIFCHandle, IFCEntityType.IfcElement)) { return; } } IFCFile ifcFile = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IFCAnyHandle portOut = null; IFCAnyHandle portIn = null; // ----------------------- In Port ---------------------- { string guid = GUIDUtil.CreateGUID(); IFCFlowDirection flowDir = (isBiDirectional) ? IFCFlowDirection.SourceAndSink : IFCFlowDirection.Sink; IFCAnyHandle localPlacement = CreateLocalPlacementForConnector(exporterIFC, connector, inElementIFCHandle, flowDir); string portName = "InPort_" + inElement.Id; string portType = "Flow"; // Assigned as Port.Description portIn = IFCInstanceExporter.CreateDistributionPort(exporterIFC, null, guid, ownerHistory, localPlacement, null, flowDir); IFCAnyHandleUtil.OverrideNameAttribute(portIn, portName); IFCAnyHandleUtil.SetAttribute(portIn, "Description", portType); // Attach the port to the element guid = GUIDUtil.CreateGUID(); string connectionName = inElement.Id + "|" + guid; IFCAnyHandle connectorIn = IFCInstanceExporter.CreateRelConnectsPortToElement(ifcFile, guid, ownerHistory, connectionName, portType, portIn, inElementIFCHandle); } // ----------------------- Out Port---------------------- { string guid = GUIDUtil.CreateGUID(); IFCFlowDirection flowDir = (isBiDirectional) ? IFCFlowDirection.SourceAndSink : IFCFlowDirection.Source; IFCAnyHandle localPlacement = CreateLocalPlacementForConnector(exporterIFC, connected, outElementIFCHandle, flowDir); string portName = "OutPort_" + outElement.Id; string portType = "Flow"; // Assigned as Port.Description portOut = IFCInstanceExporter.CreateDistributionPort(exporterIFC, null, guid, ownerHistory, localPlacement, null, flowDir); IFCAnyHandleUtil.OverrideNameAttribute(portOut, portName); IFCAnyHandleUtil.SetAttribute(portOut, "Description", portType); // Attach the port to the element guid = GUIDUtil.CreateGUID(); string connectionName = outElement.Id + "|" + guid; IFCAnyHandle connectorOut = IFCInstanceExporter.CreateRelConnectsPortToElement(ifcFile, guid, ownerHistory, connectionName, portType, portOut, outElementIFCHandle); } // ----------------------- Out Port -> In Port ---------------------- if (portOut != null && portIn != null) { Element elemToUse = (inElement.Id.IntegerValue < outElement.Id.IntegerValue) ? inElement : outElement; string guid = GUIDUtil.CreateGUID(); IFCAnyHandle realizingElement = null; string connectionName = ExporterUtil.GetGlobalId(portIn) + "|" + ExporterUtil.GetGlobalId(portOut); string connectionType = "Flow"; // Assigned as Description IFCInstanceExporter.CreateRelConnectsPorts(ifcFile, guid, ownerHistory, connectionName, connectionType, portIn, portOut, realizingElement); AddConnectionInternal(inElement.Id, outElement.Id); } // Add the handles to the connector system. HashSet <MEPSystem> systemList = new HashSet <MEPSystem>(); try { MEPSystem system = connector.MEPSystem; if (system != null) { systemList.Add(system); } } catch { } if (isElectricalDomain) { foreach (MEPSystem system in systemList) { ExporterCacheManager.SystemsCache.AddElectricalSystem(system.Id); ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, inElementIFCHandle); ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, outElementIFCHandle); ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, portIn); ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, portOut); } } else { foreach (MEPSystem system in systemList) { ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, inElementIFCHandle); ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, outElementIFCHandle); ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, portIn); ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, portOut); } } }
static void AddConnection(ExporterIFC exporterIFC, Connector connector, Connector connected, bool isBiDirectional, bool isElectricalDomain) { // Port connection is changed in IFC4 to use IfcRelNests for static connection. IfcRelConnectsPortToElement is used for a dynamic connection and it is restricted to IfcDistributionElement bool isIFC4AndAbove = !ExporterCacheManager.ExportOptionsCache.ExportAsOlderThanIFC4; Element inElement = connector.Owner; Element outElement = connected.Owner; if (isElectricalDomain) { // We may get a connection back to the original element. Ignore it. if (inElement.Id == outElement.Id) { return; } // Check the outElement to see if it is a Wire; if so, get its connections and "skip" the wire. if (outElement is Wire) { if (m_ProcessedWires.Contains(outElement.Id)) { return; } m_ProcessedWires.Add(outElement.Id); ExporterCacheManager.SystemsCache.AddElectricalSystem((outElement as Wire).MEPSystem.Id); try { ConnectorSet wireConnectorSet = MEPCache.GetConnectorsForWire(outElement as Wire); if (wireConnectorSet != null) { foreach (Connector connectedToWire in wireConnectorSet) { ProcessConnections(exporterIFC, connectedToWire, connector); } } } catch { } return; } } // Check if the connection already exist if (ConnectionExists(inElement.Id, outElement.Id)) { return; } if (isBiDirectional) { if (ConnectionExists(outElement.Id, inElement.Id)) { return; } } IFCAnyHandle inElementIFCHandle = ExporterCacheManager.MEPCache.Find(inElement.Id); IFCAnyHandle outElementIFCHandle = ExporterCacheManager.MEPCache.Find(outElement.Id); // Note: In IFC4 the IfcRelConnectsPortToElement should be used for a dynamic connection. The static connection should use IfcRelNests if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { if (inElementIFCHandle == null || outElementIFCHandle == null || !IFCAnyHandleUtil.IsSubTypeOf(inElementIFCHandle, IFCEntityType.IfcObjectDefinition) || !IFCAnyHandleUtil.IsSubTypeOf(outElementIFCHandle, IFCEntityType.IfcObjectDefinition)) { return; } } else { if (inElementIFCHandle == null || outElementIFCHandle == null || !IFCAnyHandleUtil.IsSubTypeOf(inElementIFCHandle, IFCEntityType.IfcElement) || !IFCAnyHandleUtil.IsSubTypeOf(outElementIFCHandle, IFCEntityType.IfcElement)) { return; } } IFCFile ifcFile = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; IFCAnyHandle portOut = null; IFCAnyHandle portIn = null; // Note: the GUIDs below are stable under the assumption that there is only one distribution // port from element A to element B. Also, note that we don't need the "real" GUIDs for these // elements, just stable ones. string inGuid = ExportUtils.GetExportId(inElement.Document, inElement.Id).ToString(); string outGuid = ExportUtils.GetExportId(outElement.Document, outElement.Id).ToString(); string portInGuid = null; string portOutGuid = null; // ----------------------- In Port ---------------------- { portInGuid = GUIDUtil.GenerateIFCGuidFrom("InPort" + connector.Id, inElement, outElement); IFCFlowDirection flowDir = (isBiDirectional) ? IFCFlowDirection.SourceAndSink : IFCFlowDirection.Sink; IFCAnyHandle localPlacement = CreateLocalPlacementForConnector(exporterIFC, connector, inElementIFCHandle, flowDir); portIn = IFCInstanceExporter.CreateDistributionPort(exporterIFC, null, portInGuid, ownerHistory, localPlacement, null, flowDir); string portType = "Flow"; // Assigned as Port.Description ExporterCacheManager.MEPCache.CacheConnectorHandle(connector, portIn); SetDistributionPortAttributes(portIn, connector, portType, inElement.Id, ref flowDir); // Attach the port to the element string guid = GUIDUtil.GenerateIFCGuidFrom("InPortRelConnects" + connector.Id, inElement, outElement); string connectionName = inElement.Id + "|" + guid; // Port connection is changed in IFC4 to use IfcRelNests for static connection. IfcRelConnectsPortToElement is used for a dynamic connection and it is restricted to IfcDistributionElement // The following code collects the ports that are nested to the object to be assigned later if (isIFC4AndAbove) { AddNestedMembership(inElementIFCHandle, portIn); } else { IFCInstanceExporter.CreateRelConnectsPortToElement(ifcFile, guid, ownerHistory, connectionName, portType, portIn, inElementIFCHandle); } } // ----------------------- Out Port---------------------- { portOutGuid = GUIDUtil.GenerateIFCGuidFrom("OutPort" + connector.Id, outElement, inElement); IFCFlowDirection flowDir = (isBiDirectional) ? IFCFlowDirection.SourceAndSink : IFCFlowDirection.Source; IFCAnyHandle localPlacement = CreateLocalPlacementForConnector(exporterIFC, connected, outElementIFCHandle, flowDir); portOut = IFCInstanceExporter.CreateDistributionPort(exporterIFC, null, portOutGuid, ownerHistory, localPlacement, null, flowDir); string portType = "Flow"; // Assigned as Port.Description ExporterCacheManager.MEPCache.CacheConnectorHandle(connected, portOut); SetDistributionPortAttributes(portOut, connected, portType, outElement.Id, ref flowDir); // Attach the port to the element string guid = GUIDUtil.GenerateIFCGuidFrom("OutPortRelConnects" + connector.Id.ToString(), outElement, inElement); string connectionName = outElement.Id + "|" + guid; // Port connection is changed in IFC4 to use IfcRelNests for static connection. IfcRelConnectsPortToElement is used for a dynamic connection and it is restricted to IfcDistributionElement // The following code collects the ports that are nested to the object to be assigned later if (isIFC4AndAbove) { AddNestedMembership(outElementIFCHandle, portOut); } else { IFCInstanceExporter.CreateRelConnectsPortToElement(ifcFile, guid, ownerHistory, connectionName, portType, portOut, outElementIFCHandle); } } // ----------------------- Out Port -> In Port ---------------------- if (portOut != null && portIn != null) { IFCAnyHandle realizingElement = null; string connectionName = portInGuid + "|" + portOutGuid; string connectionType = "Flow"; // Assigned as Description string guid = GUIDUtil.GenerateIFCGuidFrom(IFCEntityType.IfcRelConnectsPorts, portIn, portOut); IFCInstanceExporter.CreateRelConnectsPorts(ifcFile, guid, ownerHistory, connectionName, connectionType, portIn, portOut, realizingElement); AddConnectionInternal(inElement.Id, outElement.Id); } // Add the handles to the connector system. HashSet <MEPSystem> systemList = new HashSet <MEPSystem>(); try { MEPSystem system = connector.MEPSystem; if (system != null) { systemList.Add(system); } } catch { } if (isElectricalDomain) { foreach (MEPSystem system in systemList) { ExporterCacheManager.SystemsCache.AddElectricalSystem(system.Id); ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, inElementIFCHandle); ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, outElementIFCHandle); ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, portIn); ExporterCacheManager.SystemsCache.AddHandleToElectricalSystem(system.Id, portOut); } } else { foreach (MEPSystem system in systemList) { ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, inElementIFCHandle); ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, outElementIFCHandle); ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, portIn); ExporterCacheManager.SystemsCache.AddHandleToBuiltInSystem(system, portOut); } } }