public static bool TryGetCentroidVolume(this Solid s, out CentroidVolume cv)
 {
     cv = null;
     try
     {
         if (null != s &&
             0 < s.Faces.Size &&
             SolidUtils.IsValidForTessellation(s) &&
             (null != (cv = new CentroidVolume()
         {
             Centroid = s.ComputeCentroid(),
             Volume = s.Volume
         }
                       )))
         {
             return(true);
         }
     }
     catch (Exception e)
     {
     }
     return(false);
 }
        /// <summary>
        /// Calculate centroid for all non-empty solids
        /// found for the given element. Family instances
        /// may have their own non-empty solids, in which
        /// case those are used, otherwise the symbol geometry.
        /// The symbol geometry could keep track of the
        /// instance transform to map it to the actual
        /// project location. Instead, we ask for
        /// transformed geometry to be returned, so the
        /// resulting solids are already in place.
        /// </summary>
        public static bool TryGetCentroid(
            this Element e,
            Options opt,
            out CentroidVolume cvol)
        {
            cvol = null;
            GeometryElement geo      = e.get_Geometry(opt);
            CentroidVolume  combined = new CentroidVolume();

            if (null == geo)
            {
                return(false);
            }

            // List of pairs of centroid, volume for each solid

            List <CentroidVolume> a
                = new List <CentroidVolume>();

            if (e is FamilyInstance)
            {
                geo = geo.GetTransformed(
                    Transform.Identity);
            }

            GeometryInstance inst = null;

            foreach (GeometryObject obj in geo)
            {
                if (!TryGetCentroidVolume(obj as Solid, out var cv))
                {
                    continue;
                }
                a.Add(cv);
                inst = obj as GeometryInstance;
            }

            if (0 == a.Count && null != inst)
            {
                geo = inst.GetSymbolGeometry();

                foreach (GeometryObject obj in geo)
                {
                    if (!TryGetCentroidVolume(obj as Solid, out var cv))
                    {
                        continue;
                    }
                    a.Add(cv);
                }
            }

            // Get the total centroid from the partial
            // contributions. Each contribution is weighted
            // with its associated volume, which needs to
            // be factored out again at the end.

            try
            {
                if (0 < a.Count)
                {
                    combined = new CentroidVolume();
                    bool unweighted = false;

                    // Revit may give us volumes of 0.
                    // In which case we will not do a
                    // weighted calculation, which will
                    // throw a divide by zero exception.
                    foreach (CentroidVolume cv2 in a)
                    {
                        if (cv2.Volume == 0)
                        {
                            unweighted = true;
                            break;
                        }
                    }
                    if (unweighted)
                    {
                        foreach (var cv2 in a)
                        {
                            combined.Centroid += cv2.Centroid;
                        }
                        combined.Centroid /= a.Count;
                    }
                    else
                    {
                        foreach (var cv2 in a)
                        {
                            combined.Centroid += cv2.Volume * cv2.Centroid;
                            combined.Volume   += cv2.Volume;
                        }
                        combined.Centroid /= (a.Count == 0 ? 1 : a.Count) * (combined.Volume == 0 ? 1 : combined.Volume);
                    }
                }
            } catch (Exception ex)
            {
                combined = null;
            }
            cvol = combined;
            return(combined != null && combined != default(CentroidVolume));
        }