An aggregate attribute is an attribute that is represented by an application instance. This means that one application instance is included (acts as a part of an assembly) in another instance (a container). This section illustrates how to get access to aggregate attributes and sequentially walk through a collection of such attributes.
The first case of an application instance with an aggregate attribute is when each attribute is represented with a handle to another instance. For example, a polyline object is a set of points that defines the polyline route. A polyline can be stored in an .ifc file as the following:
#173= IFCCARTESIANPOINT((-2232.66666666677,-11000.));
#175= IFCCARTESIANPOINT((3767.33333333345,-11000.));
#177= IFCCARTESIANPOINT((3767.33333333345,7000.));
#179= IFCCARTESIANPOINT((-1534.66666666668,7000.));
#181= IFCCARTESIANPOINT((-1534.66666666668,4000.));
#183= IFCCARTESIANPOINT((-2232.66666666677,4000.));
#185= IFCPOLYLINE((#173,#175,#177,#179,#181,#183,#173));
The polyline (handle 185) is described with six points; each point is a separate application instance. The aggregate attributes can be accessed in two ways:
sdaiGetAggrByIndex()
function).
sdaiCreateIterator()
function).
Whichever way you prefer, you have to use the sdaiAGGR
data type to store an aggregate attribute extracted from the
parent instance by calling the
sdaiGetAttrBN()
function.
To get the parent instance, use the
sdaiGetEntityById()
function.
SdaiAppInstance applicationInstance = _sdaiGetEntityById(model, 185);
if ((applicationInstance == NULL) || (sdaiErrorQuery() != sdaiNO_ERR))
return;
SdaiAggr aggregate = NULL;
if (sdaiGetAttrBN(applicationInstance, "points", sdaiAGGR, &aggregate ) == NULL)
return;
To get aggregate attribute items via an index, use the
sdaiGetAggrByIndex()
function.
This function accepts four parameters:
The function returns a raw pointer to the attribute value stored in the fourth output parameter.
First, create an array with aggregate attribute handles to read.
const SdaiInteger checkHandleData[] = { 173, 175, 177, 179, 181, 183, 173 };
const SdaiInteger checkHandleDataLength = sizeof(checkHandleData) / sizeof(checkHandleData[0]);
Get the number of aggregate attributes by calling the
sdaiGetMemberCount()
function.
The value returned by this function is used as a bound of the cycle used to iterate through attributes:
const SdaiInteger indexUpperBound = sdaiGetMemberCount(aggregate);
for (SdaiInteger instanceIndex = 0; instanceIndex < indexUpperBound; ++instanceIndex )
{
SdaiAppInstance instanceFromAggrIndex = NULL;
if (sdaiGetAggrByIndex(aggregate, instanceIndex, sdaiINSTANCE, &instanceFromAggrIndex ) != NULL)
{
if (instanceIndex >= checkHandleDataLength)
return;
if (_sdaiGetEntityId(instanceFromAggrIndex) != checkHandleData[instanceIndex])
return;
}
else
{
return;
}
}
The other way to get an aggregate attribute is to use an iterator object to get sequential access to attributes.
To get the iterator, use the sdaiCreateIterator()
function.
For interaction with the attributes collection, use the following functions:
sdaiBeginning()
for moving to the beginning of the attributes collection.
sdaiNext()
for moving to the next attribute item.
sdaiGetAggrByIterator()
for getting the attribute value.
SdaiIterator aggregateIterator = sdaiCreateIterator(aggregate);
if(sdaiErrorQuery() != sdaiNO_ERR)
return;
SdaiInteger iterationCounter = 0;
for (sdaiBeginning(aggregateIterator); sdaiNext(aggregateIterator); ++iterationCounter)
{
SdaiAppInstance instanceFromIterator = NULL;
if (sdaiGetAggrByIterator(aggregateIterator, sdaiINSTANCE, &instanceFromIterator ) != NULL)
{
if (iterationCounter >= checkHandleDataLength)
return;
if (_sdaiGetEntityId(instanceFromIterator) != checkHandleData[iterationCounter])
return;
}
}
When you do not need the iterator anymore, call the sdaiDeleteADB()
function to free the memory allocated by the iterator object:
sdaiDeleteADB(aggregateIterator);
This section illustrates how to exclude an aggregate attribute value using attribute data block functions.
Assume that your IFC model contains the following instance:
#94 = IFCUNITASSIGNMENT ((#43,#45,#46,#50,#52,#55,#57,#58,#60,#64,#69,#71,#72, #73,#74,#75,#76,#77,#82,#86,#88,#92));
The IfcUnitAssignment
instance with the handle equal to 94 consists of one field; the instance field is an aggregate attribute with a set of instance identifiers.
These identifiers refer to select data type instances:
#43= IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);
#45= IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#46= IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#50= IFCCONVERSIONBASEDUNIT(#48,.PLANEANGLEUNIT.,'DEGREE',#49);
#52= IFCSIUNIT(*,.MASSUNIT.,.KILO.,.GRAM.);
#55= IFCDERIVEDUNIT((#53,#54),.MASSDENSITYUNIT.,$);
#57= IFCSIUNIT(*,.TIMEUNIT.,$,.SECOND.);
#58= IFCSIUNIT(*,.FREQUENCYUNIT.,$,.HERTZ.);
#60= IFCSIUNIT(*,.THERMODYNAMICTEMPERATUREUNIT.,$,.DEGREE_CELSIUS.);
#64= IFCDERIVEDUNIT((#61,#62,#63),.THERMALTRANSMITTANCEUNIT.,$);
#69= IFCDERIVEDUNIT((#67,#68),.VOLUMETRICFLOWRATEUNIT.,$);
#71= IFCSIUNIT(*,.ELECTRICCURRENTUNIT.,$,.AMPERE.);
#72= IFCSIUNIT(*,.ELECTRICVOLTAGEUNIT.,$,.VOLT.);
#73= IFCSIUNIT(*,.POWERUNIT.,$,.WATT.);
#74= IFCSIUNIT(*,.FORCEUNIT.,.KILO.,.NEWTON.);
#75= IFCSIUNIT(*,.ILLUMINANCEUNIT.,$,.LUX.);
#76= IFCSIUNIT(*,.LUMINOUSFLUXUNIT.,$,.LUMEN.);
#77= IFCSIUNIT(*,.LUMINOUSINTENSITYUNIT.,$,.CANDELA.);
#82= IFCDERIVEDUNIT((#78,#79,#80,#81),.USERDEFINED.,'Luminous Efficacy');
#86= IFCDERIVEDUNIT((#84,#85),.LINEARVELOCITYUNIT.,$);
#92= IFCDERIVEDUNIT((#89,#90,#91),.USERDEFINED.,'Friction Loss');
To read and extract specific values from these aggregates:
_sdaiGetEntityById()
function call and check the result:
SdaiAppInstance applicationInstance = _sdaiGetEntityById(model, 94);
if ((applicationInstance == NULL) || (sdaiErrorQuery() != sdaiNO_ERR))
return;
sdaiGetAttrBN()
function call; then request the number of members in the aggregate
by calling the sdaiGetMemberCount()
function:
SdaiAggr aggregate = NULL;
if (sdaiGetAttrBN(applicationInstance, "units", sdaiAGGR, &aggregate) == NULL)
return;
if (sdaiGetMemberCount(aggregate) <= 0)
return;
SdaiIterator aggregateIterator = sdaiCreateIterator(aggregate);
if (sdaiErrorQuery() != sdaiNO_ERR)
return;
for (sdaiBeginning(aggregateIterator); sdaiNext(aggregateIterator);)
{
SdaiADB adbToGet = sdaiCreateEmptyADB();
if (sdaiGetAggrByIterator(aggregateIterator, sdaiADB, &adbToGet ) == NULL)
return;
SdaiInstance instanceFromAdb = NULL;
if (sdaiGetADBValue(adbToGet, sdaiINSTANCE, &instanceFromAdb ) == NULL)
return;
sdaiDeleteADB(adbToGet);
SdaiInstance instanceFromAdbSimpleGet = NULL;
if (sdaiGetAggrByIterator(aggregateIterator, sdaiINSTANCE, &instanceFromAdbSimpleGet ) == NULL)
return;
if ((instanceFromAdb != instanceFromAdbSimpleGet) || (sdaiErrorQuery() != sdaiNO_ERR))
return;
}
Inside the cycle through the items, an empty instance of the attribute data block is created
(the sdaiCreateEmptyADB()
function).
The pointer to the created ADB object
is passed to the sdaiGetAggrByIterator()
function, which fills it with the appropriate data.
To extract data contained in the attribute data block, use the
sdaiGetADBValue()
function.
When the ADB instance is not needed anymore, delete it with an sdaiDeleteADB()
function call to avoid memory leaks.
The more simple way to get an attribute data block value from the aggregate is to pass a pointer to the desired instance to the
sdaiGetAggrByIterator()
function,
and the function returns a valid value if the value of the attribute data block
can be converted to the passed instance type.
The last condition in the iterating cycle checks whether the conversion is successful.
This section describes how to read data from an aggregate attribute that contains an array of other aggregate attributes. Assume that an .ifc file contains the following application instance:
#1277= IFCRATIONALBSPLINESURFACEWITHKNOTS(
3,1,
(
(#1249,#1251), (#1253,#1255), (#1257,#1259), (#1261,#1263), (#1265,#1267), (#1269,#1271), (#1273,#1275)
),
.RULED_SURF.,.F.,.F.,.U.,(4,1,1,1,4),(2,2),(0.,0.25,0.5,0.75,1.),(0.,1.),
.UNSPECIFIED.,
(
(1.,1.),(1.,1.),(1.,1.),(1.,1.),(1.,1.),(1.,1.),(1.,1.)
)
);
This instance contains two-dimensional aggregates (highlighted with bold text). Below you can see how to read the first aggregate item from each two-dimensional aggregate.
_sdaiGetEntityById()
function:
SdaiAppInstance applicationInstance = _sdaiGetEntityById(model, 1277);
if (applicationInstance == NULL) || (sdaiErrorQuery() != sdaiNO_ERR)
return;
SdaiAggr aggregate2dControlPointsList = NULL;
if (sdaiGetAttrBN(applicationInstance, "controlpointslist", sdaiAGGR, &aggregate2dControlPointsList ) == NULL)
return;
if (sdaiErrorQuery() != sdaiNO_ERR)
return;
sdaiGetAggrByIndex()
function call:
SdaiAggr aggregateChild = NULL;
if (
(sdaiGetAggrByIndex(aggregate2dControlPointsList, 0, sdaiAGGR, &aggregateChild ) == NULL)
||
(sdaiErrorQuery() != sdaiNO_ERR)
)
{
return;
}
SdaiAppInstance childAggrAppInstnce = NULL;
if (
(sdaiGetAggrByIndex (aggregateChild, 0, sdaiINSTANCE, &childAggrAppInstnce ) == NULL)
||
(_sdaiGetEntityId(childAggrAppInstnce) != 1249)
||
(sdaiErrorQuery() != sdaiNO_ERR)
)
{
return;
}
SdaiAppInstance childAggrAppInstnce = NULL;
if (
(sdaiGetAggrByIndex (aggregateChild, 1, sdaiINSTANCE, &childAggrAppInstnce ) == NULL)
||
(_sdaiGetEntityId(childAggrAppInstnce) != 1251)
||
(sdaiErrorQuery() != sdaiNO_ERR)
)
{
return;
}
"weightsdata"
.
The next code fragment illustrates how to get access to the aggregate contents without using the ADB functionality.
First, get this aggregate with the appropriate name from the application instance.
Then extract a nested aggregate.
SdaiAggr aggregate2dWeightsData = NULL;
if ((sdaiGetAttrBN(applicationInstance, "weightsdata", sdaiAGGR, &aggregate2dWeightsData ) == NULL) || (sdaiErrorQuery() != sdaiNO_ERR))
return;
if ((sdaiGetAggrByIndex(aggregate2dWeightsData, 0, sdaiAGGR, &aggregateChild ) == NULL) || (sdaiErrorQuery() != sdaiNO_ERR))
return;
After getting the nested aggregate, call the
sdaiGetAggrByIndex()
function to get the coordinates included in the aggregate and check the result:
SdaiReal childAggrReal = NULL;
// get and check the first coordinate from the aggregate
if (
(sdaiGetAggrByIndex(aggregateChild, 0, sdaiREAL, &childAggrReal ) == NULL)
|| (!OdEqual(childAggrReal, 1.))
|| (sdaiErrorQuery() != sdaiNO_ERR)
)
{
return;
}
// get and check the second coordinate from the aggregate
if (
(sdaiGetAggrByIndex(aggregateChild, 0, sdaiREAL, &childAggrReal ) == NULL)
|| (!OdEqual(childAggrReal, 1.))
|| (sdaiErrorQuery() != sdaiNO_ERR)
)
{
return;
}
Copyright © 2002 – 2021. Open Design Alliance. All rights reserved.
|