I want to measure a simple volume (solid) element but with the code below, CurveVector is null. As it looks, CurveVector is not right for that element.
public static decimal getValueAsDecimal(Bentley.DgnPlatformNET.Elements.Element ElementIn, MSElementProperties elemPropIn) { decimal decValue = 0; CurveVector c = CurvePathQuery.ElementToCurveVector(ElementIn); if (c == null) return 0; switch (elemPropIn) { case MSElementProperties.Area: { double dArea; DPoint3d pt; DVector3d normal; c.CentroidNormalArea(out pt, out normal, out dArea); decValue = (decimal)dArea; break; } ... return decValue; }
Jean-Pierre Hundhausen said:CurveVector is not right fora simple volume (solid) element
Correct! A CurveVector contains lines, arcs etc. It may be closed, meaning that it describes an area feature.
CurveVector
Jean-Pierre Hundhausen said:I want to measure a simple volume (solid) element
Class SolidPrimitiveQuery looks like a candidate for that job, but I don't see a method to get the solid's volume.
SolidPrimitiveQuery
The C++ MicroStationAPI contains class ISolidPrimitive, which has method ComputePrincipalMoments (double &volume, DVec3dR centroid, RotMatrixR axes, DVec3dR momentxyz). It also has ComputeSecondMomentAreaProducts (that gets the solid surface area but not its volume) which is available in C#. I conclude that ComputePrincipalMoments's absence from the .NET API is an oversight. File a service request (SR) with Bentley Systems to have it included.
ISolidPrimitive
ComputePrincipalMoments (double &volume, DVec3dR centroid, RotMatrixR axes, DVec3dR momentxyz)
ComputeSecondMomentAreaProducts
ComputePrincipalMoments
Regards, Jon Summers LA Solutions
Hi Jean-Pierre,
as Jon wrote, it seems Volume property is not implemented yet in Solid element query. But there is a workaround: To obtain an element volume, you can query element EC property. Example of the code is (ignore element id, used to test the code functionality):
DgnModel activeModel = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel(); ulong id = 833; ElementId elementId = new ElementId(ref id); Element element = activeModel.FindElementById(elementId); DgnECInstanceCollection collection = DgnECManager.Manager.GetElementProperties(element, ECQueryProcessFlags.SearchAllClasses); foreach (IDgnECInstance instance in collection) { IECPropertyValue result = instance.GetPropertyValue("Volume"); if (null != result) { double volume; if (result.TryGetDoubleValue(out volume)) { ModelInfo modelInfo = activeModel.GetModelInfo(); double cubicScale = System.Math.Pow(modelInfo.UorPerMaster, 3); string ecClassName = instance.ClassDefinition.Name; MessageCenter.Instance.StatusMessage = "EC class: " + ecClassName + "; Volume: " + (volume / cubicScale).ToString(); } } }
A problem with EC properties is that they depend on their names and it's not defined anywhere that all 3D elements have "Volume" property defined. But I think it's true in this case. I tried it with primitive box (BoxSolicElement class) and parametric solid (SmartFeatureContainer class) and it works fine.
With regards,
Jan
Bentley Accredited Developer: iTwin Platform - AssociateLabyrinth Technology | dev.notes() | cad.point
Answer Verified By: Jean-Pierre Hundhausen
Jan Šlegr said:Example of the code
Good work-around!
When formatting measurements, there are several formatter classes provided by C# and C++. In your example, the VolumeFormatter will be useful. It takes care of dimensionality and UORs for you.
VolumeFormatter
Jan Šlegr said:A problem with EC properties is that they depend on their names and it's not defined anywhere that all 3D elements have "Volume" property defined.
Is there a list of the names, especially for other types? SurfaceArea did worked.Overall this worked fine and is better than my workaround to go over the Interop Element.
Mit freundlichen Grüßen / Best regardsJean-Pierre Hundhausen
| AB_DATE Engineering Software | ab-date.de |
Jean-Pierre Hundhausen said:Is there a list of the names, especially for other types? SurfaceArea did worked.
No ... yes ;-)
No: There is not any official list of EC properties for a particular element type(s).
Yes: You can find this information yourself easily, even by two different ways (but both require some knowledge and detective work ;-):
Jean-Pierre Hundhausen said:Overall this worked fine and is better than my workaround to go over the Interop Element.
In fact it's quite standard now in MicroStation: EC description has become Lingua Franca internally, because it allows to describe different data structures in standardized format.
Jean-Pierre Hundhausen said:Is there a list of the names, especially for other types?
Look at the EC schemas you will find in C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\ECSchemas. For example, SurfaceArea is defined in BaseElementSchema as a property of classes MstnSurface and MstnVolume.
C:\Program Files\Bentley\MicroStation CONNECT Edition\MicroStation\ECSchemas
BaseElementSchema
MstnSurface
MstnVolume
Jon Summers said:In your example, the VolumeFormatter will be useful. It takes care of dimensionality and UORs for you.
Yes, I agree, these classes makes value formatting simpler:
DgnECInstanceCollection collection = DgnECManager.Manager.GetElementProperties(element, ECQueryProcessFlags.SearchAllClasses); foreach (IDgnECInstance instance in collection) { MessageCenter.Instance.StatusMessage = "EC class " + instance.ClassDefinition.Name + " evaluated"; IECPropertyValue result = instance.GetPropertyValue("Volume"); if (null != result) { double volume; if (result.TryGetDoubleValue(out volume)) { VolumeFormatter formatter = new VolumeFormatter(activeModel); formatter.ShowUnitLabel = true; MessageCenter.Instance.StatusMessage = "Volume: " + formatter.ToString(volume); } } }
There are more way how to make this "proof of concept" code better, e.g. to do not search all classes and iterate all results, but to search only for classes relevant for "Volume" information. Often it will be not big difference, but when working with parametric solids, every input geometry and every operation is represented by own EC class, so the collection can contains tens of classes, where only "root" SmartFeatureCollection provides "Volume" property.
Regards,