Exemple #1
0
        /// <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>
        CentroidVolume GetCentroid(
            Element e,
            Options opt)
        {
            CentroidVolume cv = null;

              GeometryElement geo = e.get_Geometry( opt );

              Solid s;

              if( null != geo )
              {
            // List of pairs of centroid, volume for each solid

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

            Document doc = e.Document;

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

            GeometryInstance inst = null;

            CentroidVolume cv1;

            foreach( GeometryObject obj in geo )
            {
              s = obj as Solid;

              if( null != s
            && 0 < s.Faces.Size
            && SolidUtils.IsValidForTessellation( s )
            && (null != ( cv1 = GetCentroid( s ) ) ) )
              {
            a.Add( cv1 );
              }
              inst = obj as GeometryInstance;
            }

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

              foreach( GeometryObject obj in geo )
              {
            s = obj as Solid;

            if( null != s
              && 0 < s.Faces.Size
              && SolidUtils.IsValidForTessellation( s )
              && (null != ( cv1 = GetCentroid( s ) ) ) )
            {
              a.Add( cv1 );
            }
              }
            }

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

            if( 0 < a.Count )
            {
              cv = new CentroidVolume();
              foreach( CentroidVolume cv2 in a )
              {
            cv.Centroid += cv2.Volume * cv2.Centroid;
            cv.Volume += cv2.Volume;
              }
              cv.Centroid /= a.Count * cv.Volume;
            }
              }
              return cv;
        }
Exemple #2
0
        /*
        void f()
        {
          var cx, cy, cz, volume, v, i, x1, y1, z1, x2, y2, z2, x3, y3, z3;
          volume = 0;
          cx = 0; cy = 0; cz = 0;
          // Assuming vertices are in vertX[i], vertY[i], and vertZ[i]
          // and faces are faces[i, j] where the first index indicates the
          // face and the second index indicates the vertex of that face
          // The value in the faces array is an index into the vertex array
          i = 0;
          repeat (numFaces) {
        x1 = vertX[faces[i, 0]]; y1 = vertY[faces[i, 0]]; z1 = vertZ[faces[i, 0]];
        x2 = vertX[faces[i, 1]]; y2 = vertY[faces[i, 1]]; z2 = vertZ[faces[i, 1]];
        x3 = vertX[faces[i, 2]]; y3 = vertY[faces[i, 2]]; z3 = vertZ[faces[i, 2]];
        v = x1*(y2*z3 - y3*z2) + y1*(z2*x3 - z3*x2) + z1*(x2*y3 - x3*y2);
        volume += v;
        cx += (x1 + x2 + x3)*v;
        cy += (y1 + y2 + y3)*v;
        cz += (z1 + z2 + z3)*v;
        i += 1;
          }
          // Set centroid coordinates to their final value
          cx /= 4 * volume;
          cy /= 4 * volume;
          cz /= 4 * volume;
          // And, just in case you want to know the total volume of the model:
          volume /= 6;
        }
        */
        CentroidVolume GetCentroid( Solid solid )
        {
            CentroidVolume cv = new CentroidVolume();
              double v;
              XYZ v0, v1, v2;

              SolidOrShellTessellationControls controls
            = new SolidOrShellTessellationControls();

              controls.LevelOfDetail = 0;

              TriangulatedSolidOrShell triangulation = null;

              try
              {
            triangulation
              = SolidUtils.TessellateSolidOrShell(
            solid, controls );
              }
              catch( Autodesk.Revit.Exceptions
            .InvalidOperationException )
              {
            return null;
              }

              int n = triangulation.ShellComponentCount;

              for( int i = 0; i < n; ++i )
              {
            TriangulatedShellComponent component
              = triangulation.GetShellComponent( i );

            int m = component.TriangleCount;

            for( int j = 0; j < m; ++j )
            {
              TriangleInShellComponent t
            = component.GetTriangle( j );

              v0 = component.GetVertex( t.VertexIndex0 );
              v1 = component.GetVertex( t.VertexIndex1 );
              v2 = component.GetVertex( t.VertexIndex2 );

              v = v0.X*(v1.Y*v2.Z - v2.Y*v1.Z)
            + v0.Y*(v1.Z*v2.X - v2.Z*v1.X)
            + v0.Z*(v1.X*v2.Y - v2.X*v1.Y);

              cv.Centroid += v * (v0 + v1 + v2);
              cv.Volume += v;
            }
              }

              // Set centroid coordinates to their final value

              cv.Centroid /= 4 * cv.Volume;

              XYZ diffCentroid = cv.Centroid
            - solid.ComputeCentroid();

              Debug.Assert( 0.6 > diffCentroid.GetLength(),
            "expected centroid approximation to be "
            + "similar to solid ComputeCentroid result" );

              // And, just in case you want to know
              // the total volume of the model:

              cv.Volume /= 6;

              double diffVolume = cv.Volume - solid.Volume;

              Debug.Assert( 0.3 > Math.Abs(
            diffVolume / cv.Volume ),
            "expected volume approximation to be "
            + "similar to solid Volume property value" );

              return cv;
        }
Exemple #3
0
        /// <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>
        CentroidVolume GetCentroid(
            Element e,
            Options opt)
        {
            CentroidVolume cv = null;

            GeometryElement geo = e.get_Geometry(opt);

            Solid s;

            if (null != geo)
            {
                // List of pairs of centroid, volume for each solid

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

                Document doc = e.Document;

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

                GeometryInstance inst = null;

                CentroidVolume cv1;

                foreach (GeometryObject obj in geo)
                {
                    s = obj as Solid;

                    if (null != s &&
                        0 < s.Faces.Size &&
                        SolidUtils.IsValidForTessellation(s) &&
                        (null != (cv1 = GetCentroid(s))))
                    {
                        a.Add(cv1);
                    }
                    inst = obj as GeometryInstance;
                }

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

                    foreach (GeometryObject obj in geo)
                    {
                        s = obj as Solid;

                        if (null != s &&
                            0 < s.Faces.Size &&
                            SolidUtils.IsValidForTessellation(s) &&
                            (null != (cv1 = GetCentroid(s))))
                        {
                            a.Add(cv1);
                        }
                    }
                }

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

                if (0 < a.Count)
                {
                    cv = new CentroidVolume();
                    foreach (CentroidVolume cv2 in a)
                    {
                        cv.Centroid += cv2.Volume * cv2.Centroid;
                        cv.Volume   += cv2.Volume;
                    }
                    cv.Centroid /= a.Count * cv.Volume;
                }
            }
            return(cv);
        }
Exemple #4
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication    uiapp = commandData.Application;
            UIDocument       uidoc = uiapp.ActiveUIDocument;
            Application      app   = uiapp.Application;
            Document         doc   = uidoc.Document;
            List <ElementId> ids   = new List <ElementId>();
            Selection        sel   = uidoc.Selection;
            //SelElementSet set = sel.Elements; // 2014
            ICollection <ElementId> selids = sel.GetElementIds(); // 2015

            //if( 0 < set.Size ) // 2014
            if (0 < selids.Count) // 2015
            {
                //foreach( Element e in set ) // 2014
                //{
                //  ids.Add( e.Id ); // 2014
                //}

                ids.AddRange(selids); // 2015
            }
            else
            {
                if (ViewType.Internal == doc.ActiveView.ViewType)
                {
                    TaskDialog.Show(_caption,
                                    "Cannot pick elements in this view: "
                                    + doc.ActiveView.Name);

                    return(Result.Failed);
                }

                try
                {
                    IList <Reference> refs = sel.PickObjects(
                        ObjectType.Element,
                        "Please select some elements");

                    foreach (Reference r in refs)
                    {
                        ids.Add(r.ElementId);
                    }
                }
                catch (Autodesk.Revit.Exceptions.OperationCanceledException)
                {
                    return(Result.Cancelled);
                }
            }

            Options opt = app.Create.NewGeometryOptions();

            foreach (ElementId id in ids)
            {
                Element e = doc.GetElement(id);

                CentroidVolume cv = GetCentroid(e, opt);

                Debug.Print("{0} {1}",
                            (null == cv ? "<nil>" : cv.ToString()),
                            ElementDescription(e));
            }
            return(Result.Succeeded);
        }
Exemple #5
0
        /*
         * void f()
         * {
         * var cx, cy, cz, volume, v, i, x1, y1, z1, x2, y2, z2, x3, y3, z3;
         * volume = 0;
         * cx = 0; cy = 0; cz = 0;
         * // Assuming vertices are in vertX[i], vertY[i], and vertZ[i]
         * // and faces are faces[i, j] where the first index indicates the
         * // face and the second index indicates the vertex of that face
         * // The value in the faces array is an index into the vertex array
         * i = 0;
         * repeat (numFaces) {
         *  x1 = vertX[faces[i, 0]]; y1 = vertY[faces[i, 0]]; z1 = vertZ[faces[i, 0]];
         *  x2 = vertX[faces[i, 1]]; y2 = vertY[faces[i, 1]]; z2 = vertZ[faces[i, 1]];
         *  x3 = vertX[faces[i, 2]]; y3 = vertY[faces[i, 2]]; z3 = vertZ[faces[i, 2]];
         *  v = x1*(y2*z3 - y3*z2) + y1*(z2*x3 - z3*x2) + z1*(x2*y3 - x3*y2);
         *  volume += v;
         *  cx += (x1 + x2 + x3)*v;
         *  cy += (y1 + y2 + y3)*v;
         *  cz += (z1 + z2 + z3)*v;
         *  i += 1;
         * }
         * // Set centroid coordinates to their final value
         * cx /= 4 * volume;
         * cy /= 4 * volume;
         * cz /= 4 * volume;
         * // And, just in case you want to know the total volume of the model:
         * volume /= 6;
         * }
         */

        CentroidVolume GetCentroid(Solid solid)
        {
            CentroidVolume cv = new CentroidVolume();
            double         v;
            XYZ            v0, v1, v2;

            SolidOrShellTessellationControls controls
                = new SolidOrShellTessellationControls();

            controls.LevelOfDetail = 0;

            TriangulatedSolidOrShell triangulation = null;

            try
            {
                triangulation
                    = SolidUtils.TessellateSolidOrShell(
                          solid, controls);
            }
            catch (Autodesk.Revit.Exceptions
                   .InvalidOperationException)
            {
                return(null);
            }

            int n = triangulation.ShellComponentCount;

            for (int i = 0; i < n; ++i)
            {
                TriangulatedShellComponent component
                    = triangulation.GetShellComponent(i);

                int m = component.TriangleCount;

                for (int j = 0; j < m; ++j)
                {
                    TriangleInShellComponent t
                        = component.GetTriangle(j);

                    v0 = component.GetVertex(t.VertexIndex0);
                    v1 = component.GetVertex(t.VertexIndex1);
                    v2 = component.GetVertex(t.VertexIndex2);

                    v = v0.X * (v1.Y * v2.Z - v2.Y * v1.Z)
                        + v0.Y * (v1.Z * v2.X - v2.Z * v1.X)
                        + v0.Z * (v1.X * v2.Y - v2.X * v1.Y);

                    cv.Centroid += v * (v0 + v1 + v2);
                    cv.Volume   += v;
                }
            }

            // Set centroid coordinates to their final value

            cv.Centroid /= 4 * cv.Volume;

            XYZ diffCentroid = cv.Centroid
                               - solid.ComputeCentroid();

            Debug.Assert(0.6 > diffCentroid.GetLength(),
                         "expected centroid approximation to be "
                         + "similar to solid ComputeCentroid result");

            // And, just in case you want to know
            // the total volume of the model:

            cv.Volume /= 6;

            double diffVolume = cv.Volume - solid.Volume;

            Debug.Assert(0.3 > Math.Abs(
                             diffVolume / cv.Volume),
                         "expected volume approximation to be "
                         + "similar to solid Volume property value");

            return(cv);
        }