Questions similar to this appear on the Bentley Discussion Groups. These questions, or something like them, appeared in the MDL discussion group.
Q Questions about metrics measurement with MDL pop up occasionally
A
The answers to those questions are simple, but confused because of the MDL API function names and that some functions
operate on an MSElementUnion (same as MSElement) and others operate on
MSElementDescrs. Here are some hints to guide you through the maze
| Function | Measures | Constraint | Accepts Element Types |
|---|---|---|---|
| mdlMeasure_elmDscrArea | surface area | planar shapes only | shapes, ellipses, complex shapes and closed B-spline curves |
| mdlMeasure_areaProperties | surface area | planar shapes and SmartSurfaces1 | |
| mdlMeasure_areaPropertiesXY | surface area | ignores Z component | planar shapes only |
| mdlMeasure_surfaceProperties | surface area | planar and non-planar shapes including SmartSurfaces1 | |
| mdlMeasure_polygonArea | area of polygon | array of points that define a polygon (not an element) | |
| mdlMeasure_volumeProperties | volume | type 19 and SmartSolids1 |
1 For versions of MicroStation prior to XM, the measurement functions do not work with SmartSurfaces or SmartSolids.
If you are writing code for MicroStation V8.5 or earlier, you need to use the mdlKISolid_xxx function family
to measure SmartSurfaces and SmartSolids.
This function extracts a list of vertices from a linear element.
BoolInt example_getVertexList
(
ULong filePos, // => File position of element to measure
DgnModelRefP modelRef // => Model reference of element
)
{
BoolInt rc = FALSE;
MSElement object;
if (SUCCESS == mdlElement_read (&object, modelRef, filePos))
{
int nPoints = mdlLinear_getPointCount (&object);
DPoint3d* points = (DPoint3d*)calloc (nPoints, sizeof (DPoint3d));
if (NULL != points
&&
SUCCESS == mdlLinear_extract (points, &nPoints, object, modelRef))
{
if (2 == nPoints)
{
printf ("Length=%.2lf\n", mdlVec_distance ((1 + points), (0 + points));
}
else if (2 < nPoints)
{
double total = 0.0;
int i;
for (i = 1; i < nPoints; ++i)
{
total += mdlVec_distance ((i + points), (i - 1 + points));
}
printf ("Total length=%.2lf\n", total);
}
rc = TRUE;
free (points);
}
}
return rc;
}
This function gets the coordinate of the start and end point of a linear element. You can also ask for the corresponding tangents (slope or angle) of each end point.
BoolInt example_measureLengthFromEndPoints
(
ULong filePos, // => File position of shape element to measure
DgnModelRefP modelRef // => Model reference of shape element
)
{
BoolInt rc = FALSE;
DPoint3d startPoint;
DPoint3d endPoint;
MSElementDescr* pObject = NULL;
if (0 < mdlElmdscr_readToMaster (&pObject, filePos, modelRef, FALSE, NULL))
{
if (SUCCESS == mdlElmdscr_extractEndPoints (&startPoint, NULL, &endPoint, NULL, pObject))
{
printf ("Length=%.2lf\n", mdlVec_distance (&endPoint, &startPoint));
rc = TRUE;
}
mdlElmdscr_freeAll (&pObject);
}
return rc;
}
This function analyses a linear or area element and extracts mechanical properties such as length (or perimeter of a shape), centroid, and various moments.
BoolInt example_measureLinear
(
ULong filePos, // => File position of element to measure
DgnModelRefP modelRef // => Model reference of element
)
{
BoolInt rc = FALSE;
double length = 0.0;
const double tolerance = 0.01;
MSElementDescr* pLinear = NULL;
if (0 < mdlElmdscr_readToMaster (&pLinear, filePos, modelRef, FALSE, NULL))
{
if (SUCCESS == mdlMeasure_linearProperties (&perimeter, &area, NULL, NULL, NULL, NULL, NULL, NULL, NULL, pLinear, tolerance))
{
printf ("Length=%.2lf\n", length);
rc = TRUE;
}
mdlElmdscr_freeAll (&pLinear);
}
return rc;
}
This function analyses an area element and extracts mechanical properties such as area, perimeter,
centroid, and various moments.
If you want just the area of an element, then mdlMeasure_elmDscrArea () may be simpler to use.
mdlMeasure_polygonArea () calculates the area and perimeter of a closed shape expressed as a
list of DPoint3d vertices.
BoolInt example_measureArea
(
ULong filePos, // => File position of shape element to measure
DgnModelRefP modelRef // => Model reference of shape element
)
{
BoolInt rc = FALSE;
double area = 0.0;
double perimeter = 0.0;
const double tolerance = 0.01;
MSElementDescr* pShape = NULL;
if (0 < mdlElmdscr_readToMaster (&pShape, filePos, modelRef, FALSE, NULL))
{
if (SUCCESS == mdlMeasure_areaProperties (&perimeter, &area, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, pShape, tolerance))
{
printf ("Area=%.2lf Perimeter=%.2lf\n", area, perimeter);
rc = TRUE;
}
mdlElmdscr_freeAll (&pShape);
}
return rc;
}
This function analyses an solid element and extracts mechanical properties such as the principal moments, and the principal axes of an element.
Depending on your version of MicroStation, this function may or may not work with SmartSolid elements.
mdlMeasure_volumeProperties does not work with SmartSolid elements: type 19 solids only
mdlMeasure_volumeProperties works with SmartSolid elements
Return to MDL articles index.