[CE U13 C#] Measure Volume Elements

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;
      }

Parents
  • 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

    Answer Verified By: Jean-Pierre Hundhausen 

  • 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.

     
    Regards, Jon Summers
    LA Solutions

  • 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,

      Jan

Reply
  • 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,

      Jan

Children
No Data