Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 8

Plumbing example program (C++)

By Peter Bonsma and Pim van den Helm Based on the IFC file Plumbing.ifc created by Arkey (Arie van Kranenburg) The program will go through the plumbing system in an IFC-file (in this case the plumbing.ifc file). To go through the complete structure of the plumbing system 6 steps are defined. Within each step one or more specific objects are looked up based on a specific relation. The name of all these relevant objects will be written to screen together with the step. Each step is written in a separate function and is explained in more detail in this document. The functions are part of the CExampleDlg class in this example, explaining the namespace used before each function. 1. FirstStep => find the IfcDistributionPort that is the beginning of a plumbing system This function will check each IfcDistributionPorts if it is connected to another IfcDistributionPort. The port that has no connection to any other distribution port is the beginning of the plumbing system. Meaning: connectedTo = empty connectedFrom = empty The found IfcDistributionPort will be further analyzed in the second step.

void CExampleDlg::FirstStep() { int DistributionPort, *DistributionPorts, noDistributionPorts; DistributionPorts = sdaiGetEntityExtentBN(model, "IFCDISTRIBUTIONPORT"); noDistributionPorts = sdaiGetMemberCount(DistributionPorts); int i = 0; while (i < noDistributionPorts) { int connectedTo = 0, connectedFrom = 0; engiGetAggrElement(DistributionPorts, i, sdaiINSTANCE, &DistributionPort); sdaiGetAttrBN(DistributionPort, "ConnectedTo", sdaiINSTANCE, &connectedTo); sdaiGetAttrBN(DistributionPort, "ConnectedFrom", sdaiINSTANCE, &connectedFrom); if (connectedTo == 0 && connectedFrom == 0) { char *name; sdaiGetAttrBN(DistributionPort, "Name", 10, &name); result_text = CString("1 DistributionPort = ") + CString(name); m_Result.SetWindowTextA(result_text); SecondStep(DistributionPort); } i++;

} }

2. SecondStep => find the IfcFlowSegment an IfcDistributionPort belongs to An IfcDistributionPort is contained in an IfcRelConnectsPortToElement, describing to what object a port belongs. This function will find the object to which a port (given as argument) belongs to. With this object and the port to find it the ThirdStep will be perfomed. Note: Because the plumbing file is known, it is also known that the found element will be of the IfcFlowSegment type. This step assumes this and makes it possible to continue with the ThirdStep expecting an IfcFlowSegment.
void CExampleDlg::SecondStep(int DistributionPort) { int RelConnectsPortToElement = 0, FlowSegment = 0; sdaiGetAttrBN(DistributionPort, "ContainedIn", 6, &RelConnectsPortToElement);

sdaiGetAttrBN(RelConnectsPortToElement, "RelatedElement", 6, &FlowSegment); char *name; sdaiGetAttrBN(FlowSegment, "Name", 10, &name); result_text += CString("\r\n2 FlowSegment = ") + CString(name); m_Result.SetWindowTextA(result_text); ThirdStep(FlowSegment, DistributionPort);

3. ThirdStep => find the other IfcDistributionPort of an IfcFlowSegment An IfcFlowSegment contains only two IfcDistributionPorts. Similar to finding the IfcFlowSegment in the previous step, a port can be found from an object. But now more than one ports will be found with one port being the original port (given as argument). The other IfcDistributionPort is the one that this function will look for. If there is actually only one other port and one original port is also checked. To find the other IfcDistributionPort the port in the IfcRelConnectPortToElements belonging to the IfcFlowSegment are compared with the original port. Matching ports are only counted to check if there is only one original port. Not matching ports will be further processed by the FourthStep and counted to check that there is only one other port.

void CExampleDlg::ThirdStep(int FlowSegment, int OrgDistributionPort) { int RelConnectsPortToElement = 0, *RelConnectsPortToElements = 0, noRelConnectsPortToElements; sdaiGetAttrBN(FlowSegment, "HasPorts", 2, &RelConnectsPortToElements); noRelConnectsPortToElements = sdaiGetMemberCount(RelConnectsPortToElements); int i = 0, relevantPortsFound = 0, originalPortsFound = 0; while (i < noRelConnectsPortToElements) { int DistributionPort = 0; engiGetAggrElement(RelConnectsPortToElements, i, 6, &RelConnectsPortToElement); sdaiGetAttrBN(RelConnectsPortToElement, "RelatingPort", 6, &DistributionPort); if (DistributionPort == OrgDistributionPort) originalPortsFound++; else { char *name, tmp[10]; sdaiGetAttrBN(DistributionPort, "Name", 10, &name); relevantPortsFound++; result_text += CString("\r\n3 port ") + CString(_itoa(relevantPortsFound, tmp, 10)) + CString(": DistributionPort = ") + CString(name); m_Result.SetWindowTextA(result_text); FourthStep(DistributionPort); } i++;

} if (originalPortsFound != 1) AfxMessageBox("originalPortsFound != 1"); if (relevantPortsFound != 1) AfxMessageBox("relevantPortsFound != 1"); }

4. FourthStep => find the IfcDistributionPort connected to an IfcDistributionPort An IfcDistributionPort is contained in an IfcRelConnectsPorts, describing what ports are connected to each other. This function will find the port to which a port (given as argument) is connected. With the found port the FifthStep will be perfomed.

void CExampleDlg::FourthStep(int DistributionPort) { int RelConnectsPort = 0, RelatingDistributionPort = 0; sdaiGetAttrBN(DistributionPort, "ConnectedFrom", 6, &RelConnectsPort); sdaiGetAttrBN(RelConnectsPort, "RelatingPort", 6, &RelatingDistributionPort); char *name; sdaiGetAttrBN(RelatingDistributionPort, "Name", 10, &name); result_text += CString("\r\n4 RelatingDistributionPort = ") + CString(name); m_Result.SetWindowTextA(result_text); FifthStep(RelatingDistributionPort); }

5. FifthStep => find the object an IfcDistributionPort belongs to Similar to the SecondStep an IfcDistributionPort is contained in an IfcRelConnectsPortToElement, describing to which object a port belongs. This function will find the object to which a port (given as argument) belongs to. Different from the SecondStep is that the object will not always be an IfcFlowSegment. So depending on the type of the object a successive step will be performed with the found object and given port. The next step to perform per object type: IfcFlowSegment => ThirdStep IfcFlowFitting => SixthStep IfcFlowTerminal => end point found, no further steps needed

void CExampleDlg::FifthStep(int DistributionPort) { int RelConnectsPortToElement = 0, unknown = 0; char *name; sdaiGetAttrBN(DistributionPort, "ContainedIn", 6, &RelConnectsPortToElement); sdaiGetAttrBN(RelConnectsPortToElement, "RelatedElement", 6, &unknown); sdaiGetAttrBN(unknown, "Name", 10, &name); int FlowSegmentEntity, FlowFittingEntity, FlowTerminalEntity; FlowSegmentEntity = sdaiGetEntity(model, "IFCFLOWSEGMENT"); FlowFittingEntity = sdaiGetEntity(model, "IFCFLOWFITTING"); FlowTerminalEntity = sdaiGetEntity(model, "IFCFLOWTERMINAL"); if (sdaiGetInstanceType(unknown) == FlowSegmentEntity) { result_text += CString("\r\n5 FlowSegment = ") + CString(name); m_Result.SetWindowTextA(result_text); ThirdStep(unknown, DistributionPort); } else { if (sdaiGetInstanceType(unknown) == FlowFittingEntity) { result_text += CString("\r\n5 FlowFitting = ") + CString(name); m_Result.SetWindowTextA(result_text); SixthStep(unknown, DistributionPort); } else { if (sdaiGetInstanceType(unknown) == FlowTerminalEntity) { result_text += CString("\r\n5 Endpoint (terminal) = ") + CString(name); m_Result.SetWindowTextA(result_text); } else AfxMessageBox("Incorrect entity found in FifthStep"); } } }

6. SixthStep => find the other IfcDistributionPorts of an IfcFlowFitting An IfcFlowFitting contains two ore more IfcDistributionPorts. Similar to the ThirdStep these ports can be found. The only difference between the SixthStep and the ThirdStep is the limitation of the found ports where the ThirdStep is allowed to have only 1, and the SixthStep 1 or more. To find the other IfcDistributionPorts the port in the IfcRelConnectPortToElements belonging to the IfcFlowFitting are compared with the original port. Matching ports are only counted to check if there is only one original port. Not matching ports will be further processed by the FourthStep and counted to check that there is at least one other port.

void CExampleDlg::SixthStep(int FlowSegment, int OrgDistributionPort) { int RelConnectsPortToElement = 0, *RelConnectsPortToElements = 0, noRelConnectsPortToElements; sdaiGetAttrBN(FlowSegment, "HasPorts", 2, &RelConnectsPortToElements); noRelConnectsPortToElements = sdaiGetMemberCount(RelConnectsPortToElements); int i = 0, relevantPortsFound = 0, originalPortsFound = 0; while (i < noRelConnectsPortToElements) { int DistributionPort = 0; engiGetAggrElement(RelConnectsPortToElements, i, 6, &RelConnectsPortToElement); sdaiGetAttrBN(RelConnectsPortToElement, "RelatingPort", 6, &DistributionPort); if (DistributionPort == OrgDistributionPort) originalPortsFound++; else { char* name, tmp[10]; sdaiGetAttrBN(DistributionPort, "Name", 10, &name); relevantPortsFound++; result_text += CString("\r\n6 port") + CString(_itoa(relevantPortsFound, tmp, 10)) + CString(": DistributionPort = ") + CString(name); m_Result.SetWindowTextA(result_text); FourthStep(DistributionPort); relevantPortsFound++; } i++;

} if (originalPortsFound != 1) AfxMessageBox("originalPortsFound != 1"); if (relevantPortsFound < 1) AfxMessageBox("relevantPortsFound < 1"); }

You might also like