Beispiel #1
0
 private void AddFaceToTessellatedShapeBuilder(TessellatedFace theFace)
 {
     TessellatedShapeBuilder.AddFace(theFace);
     TessellatedFaceBoundary.Clear();
     FaceMaterialId = ElementId.InvalidElementId;
     CreatedFacesCount++;
 }
        static TessellatedShapeBuilderResult GetTessellatedSolid(
            Document doc,
            Solid transientSolid)
        {
            TessellatedShapeBuilder builder
                = new TessellatedShapeBuilder();

            ElementId idMaterial
                = new FilteredElementCollector(doc)
                  .OfClass(typeof(Material))
                  .FirstElementId();

            ElementId idGraphicsStyle
                = new FilteredElementCollector(doc)
                  .OfClass(typeof(GraphicsStyle))
                  .FirstOrDefault <Element>(gs
                                            => gs.Name.Equals("Walls"))
                  .Id;

            builder.OpenConnectedFaceSet(true);

            FaceArray faceArray = transientSolid.Faces;

            foreach (Face face in faceArray)
            {
                List <XYZ> triFace = new List <XYZ>(3);
                Mesh       mesh    = face.Triangulate();

                int triCount = mesh.NumTriangles;

                for (int i = 0; i < triCount; i++)
                {
                    triFace.Clear();

                    for (int n = 0; n < 3; n++)
                    {
                        triFace.Add(mesh.get_Triangle(i).get_Vertex(n));
                    }

                    builder.AddFace(new TessellatedFace(
                                        triFace, idMaterial));
                }
            }

            builder.CloseConnectedFaceSet();

            //return builder.Build(
            //  TessellatedShapeBuilderTarget.Solid,
            //  TessellatedShapeBuilderFallback.Abort,
            //  idGraphicsStyle ); // 2016

            builder.Fallback        = TessellatedShapeBuilderFallback.Abort;
            builder.Target          = TessellatedShapeBuilderTarget.Solid;
            builder.GraphicsStyleId = idGraphicsStyle;

            builder.Build(); // 2020

            return(builder.GetBuildResult());
        }
Beispiel #3
0
        static internal IEnumerable <GeometryObject> ToHost(this Rhino.Geometry.Mesh mesh)
        {
            List <XYZ> faceVertices = new List <XYZ>(4);

            var builder = new TessellatedShapeBuilder();

            builder.Target   = TessellatedShapeBuilderTarget.AnyGeometry;
            builder.Fallback = TessellatedShapeBuilderFallback.Mesh;

            Rhino.Geometry.Mesh[] pieces = mesh.DisjointMeshCount > 1 ?
                                           mesh.SplitDisjointPieces() :
                                           new Rhino.Geometry.Mesh[] { mesh };

            foreach (var piece in pieces)
            {
                piece.Faces.ConvertNonPlanarQuadsToTriangles(Revit.ModelAbsolutePlanarTolerance, RhinoMath.UnsetValue, 5);

                bool isOriented  = false;
                bool hasBoundary = false;
                bool isSolid     = piece.IsClosed && piece.IsManifold(true, out isOriented, out hasBoundary) && isOriented;
                var  vertices    = piece.Vertices.ToPoint3dArray();

                builder.OpenConnectedFaceSet(isSolid);
                foreach (var face in piece.Faces)
                {
                    faceVertices.Add(vertices[face.A].ToHost());
                    faceVertices.Add(vertices[face.B].ToHost());
                    faceVertices.Add(vertices[face.C].ToHost());
                    if (face.IsQuad)
                    {
                        faceVertices.Add(vertices[face.D].ToHost());
                    }

                    builder.AddFace(new TessellatedFace(faceVertices, ElementId.InvalidElementId));
                    faceVertices.Clear();
                }
                builder.CloseConnectedFaceSet();
            }

            IList <GeometryObject> objects = null;

            try
            {
                builder.Build();
                objects = builder.GetBuildResult().GetGeometricalObjects();
            }
            catch (Autodesk.Revit.Exceptions.ApplicationException e)
            {
                Debug.Fail(e.Source, e.Message);
                objects = new List <GeometryObject>();
            }

            return(objects);
        }
        /// <summary>
        /// Creates a solid from a list of points. Intented to create single face solids for solid operations.
        /// </summary>
        /// <param name="vertices">A list of XYZ vertices of the face.</param>
        /// <returns>A solid consisting of one face.</returns>
        public static Solid CreateSolid(IList <XYZ> vertices)
        {
            TessellatedShapeBuilder builder = new TessellatedShapeBuilder();

            //http://thebuildingcoder.typepad.com/blog/2014/05/directshape-performance-and-minimum-size.html
            builder.OpenConnectedFaceSet(false);
            builder.AddFace(new TessellatedFace(vertices, ElementId.InvalidElementId));
            builder.CloseConnectedFaceSet();
            builder.Build();
            TessellatedShapeBuilderResult result = builder.GetBuildResult();

            return(result.GetGeometricalObjects()[0] as Solid);
        }
        // Insipred by
        // https://github.com/DynamoDS/DynamoRevit/blob/master/src/Libraries/RevitNodes/GeometryConversion/ProtoToRevitMesh.cs
        public IList <GeometryObject> MeshToNative(Mesh mesh)
        {
            TessellatedShapeBuilderTarget   target   = TessellatedShapeBuilderTarget.Mesh;
            TessellatedShapeBuilderFallback fallback = TessellatedShapeBuilderFallback.Salvage;

            var tsb = new TessellatedShapeBuilder()
            {
                Fallback = fallback, Target = target, GraphicsStyleId = ElementId.InvalidElementId
            };

            tsb.OpenConnectedFaceSet(false);

            var vertices = ArrayToPoints(mesh.vertices, mesh.units);

            int i = 0;

            while (i < mesh.faces.Count)
            {
                var points = new List <XYZ>();

                if (mesh.faces[i] == 0)
                { // triangle
                    points = new List <XYZ> {
                        vertices[mesh.faces[i + 1]], vertices[mesh.faces[i + 2]], vertices[mesh.faces[i + 3]]
                    };
                    var face = new TessellatedFace(points, ElementId.InvalidElementId);
                    tsb.AddFace(face);
                    i += 4;
                }
                else
                { // quad
                    points = new List <XYZ> {
                        vertices[mesh.faces[i + 1]], vertices[mesh.faces[i + 2]], vertices[mesh.faces[i + 4]]
                    };
                    var face1 = new TessellatedFace(points, ElementId.InvalidElementId);
                    tsb.AddFace(face1);
                    points = new List <XYZ> {
                        vertices[mesh.faces[i + 2]], vertices[mesh.faces[i + 3]], vertices[mesh.faces[i + 4]]
                    };
                    var face2 = new TessellatedFace(points, ElementId.InvalidElementId);
                    tsb.AddFace(face2);
                    i += 5;
                }
            }

            tsb.CloseConnectedFaceSet();
            tsb.Build();
            var result = tsb.GetBuildResult();

            return(result.GetGeometricalObjects());
        }
 private void AddFaceToTessellatedShapeBuilder(TessellatedFace theFace, bool extraFace)
 {
     TessellatedShapeBuilder.AddFace(theFace);
     TessellatedFaceBoundary.Clear();
     FaceMaterialId = ElementId.InvalidElementId;
     if (extraFace)
     {
         ExtraCreatedFacesCount++;
     }
     else
     {
         CreatedFacesCount++;
     }
 }
        public static IList <GeometryObject> ToRevitType(
            this Autodesk.DesignScript.Geometry.Solid solid,
            TessellatedShapeBuilderTarget target     = TessellatedShapeBuilderTarget.Mesh,
            TessellatedShapeBuilderFallback fallback = TessellatedShapeBuilderFallback.Salvage,
            ElementId MaterialId           = null,
            bool performHostUnitConversion = true)
        {
            var rp = new DefaultRenderPackage();

            if (performHostUnitConversion)
            {
                var newSolid = solid.InHostUnits();
                newSolid.Tessellate(rp, new TessellationParameters());
                newSolid.Dispose();
            }
            else
            {
                solid.Tessellate(rp, new TessellationParameters());
            }

            var tsb = new TessellatedShapeBuilder()
            {
                Fallback = fallback, Target = target, GraphicsStyleId = ElementId.InvalidElementId
            };

            tsb.OpenConnectedFaceSet(false);

            var v = rp.MeshVertices.ToList();

            for (int i = 0; i < v.Count; i += 9)
            {
                var a = new XYZ(v[i], v[i + 1], v[i + 2]);
                var b = new XYZ(v[i + 3], v[i + 4], v[i + 5]);
                var c = new XYZ(v[i + 6], v[i + 7], v[i + 8]);

                var face = new TessellatedFace(new List <XYZ>()
                {
                    a, b, c
                }, MaterialId != null ? MaterialId : MaterialsManager.Instance.DynamoMaterialId);
                tsb.AddFace(face);
            }

            tsb.CloseConnectedFaceSet();
            tsb.Build();
            var result = tsb.GetBuildResult();

            return(result.GetGeometricalObjects());
        }
        public static IList <GeometryObject> ToRevitType(
            this Autodesk.DesignScript.Geometry.Mesh mesh,
            TessellatedShapeBuilderTarget target     = TessellatedShapeBuilderTarget.Mesh,
            TessellatedShapeBuilderFallback fallback = TessellatedShapeBuilderFallback.Salvage,
            ElementId MaterialId           = null,
            bool performHostUnitConversion = true)
        {
            var verts   = mesh.VertexPositions;
            var indices = mesh.FaceIndices;

            var tsb = new TessellatedShapeBuilder()
            {
                Fallback = fallback, Target = target, GraphicsStyleId = ElementId.InvalidElementId
            };

            tsb.OpenConnectedFaceSet(false);

            for (int faceindex = 0, count = indices.Count(); faceindex < count; faceindex++)
            {
                var f = indices[faceindex];
                //if this is a quad face triangulate it
                if (f.Count > 3)
                {
                    //and add two triangles to the tessellated shape builder
                    var tri1 = IndexGroup.ByIndices(f.B, f.C, f.A);
                    var tri2 = IndexGroup.ByIndices(f.A, f.C, f.D);

                    AddFace(tsb, tri1, verts, performHostUnitConversion, MaterialId);
                    AddFace(tsb, tri2, verts, performHostUnitConversion, MaterialId);
                }
                else
                {
                    AddFace(tsb, f, verts, performHostUnitConversion, MaterialId);
                }
            }

            tsb.CloseConnectedFaceSet();

            tsb.Build();
            var result = tsb.GetBuildResult();

            foreach (IDisposable vert in verts)
            {
                vert.Dispose();
            }

            return(result.GetGeometricalObjects());
        }
        private Mesh GetMeshBackup(IFCImportShapeEditScope shapeEditScope, IList <CurveLoop> loops,
                                   XYZ scaledExtrusionDirection, double currDepth)
        {
            if (shapeEditScope.MustCreateSolid())
            {
                return(null);
            }

            Importer.TheLog.LogError(Id, "Extrusion has an invalid definition for a solid; reverting to mesh.", false);

            MeshFromGeometryOperationResult meshResult = TessellatedShapeBuilder.CreateMeshByExtrusion(
                loops, scaledExtrusionDirection, currDepth, GetMaterialElementId(shapeEditScope));

            // will throw if mesh is not available
            return(meshResult.GetMesh());
        }
Beispiel #10
0
        private void ImportSTLDocument(
            STLDocument stlDocument,
            Document doc,
            string stlDocumentName)
        {
            StlImportProperties properties = StlImportProperties.GetProperties();

            using (Transaction t = new Transaction(doc, "Import STL"))
            {
                t.Start();

                TessellatedShapeBuilder builder = new TessellatedShapeBuilder();

                builder.OpenConnectedFaceSet(false);
                int i = 0;

                foreach (Facet facet in stlDocument.Facets)
                {
                    builder.AddFace(FromFacet(facet));
                    i++;
                }

                builder.CloseConnectedFaceSet();

                TessellatedShapeBuilderResult result
                    = builder.Build(properties.Target,
                                    properties.Fallback,
                                    properties.GraphicsStyleId);

                // Pre-release code from DevDays

                //DirectShape ds = DirectShape.CreateElement(
                //  doc, result.GetGeometricalObjects(), "A", "B");

                //ds.SetCategoryId(new ElementId(
                //  BuiltInCategory.OST_GenericModel));

                // Code updated for Revit UR1

                ElementId   categoryId = new ElementId(BuiltInCategory.OST_GenericModel);
                DirectShape ds         = DirectShape.CreateElement(doc, categoryId, "A", "B");
                ds.SetShape(result.GetGeometricalObjects());
                ds.Name = stlDocumentName;

                t.Commit();
            }
        }
        /// <summary>
        /// 三角化Solid
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="transientSolid"></param>
        /// <returns></returns>
        public static IList <GeometryObject> TessellateSolid(this Solid transientSolid, Document doc)
        {
            TessellatedShapeBuilder builder = new TessellatedShapeBuilder();

            ElementId idMaterial = new FilteredElementCollector(doc)
                                   .OfClass(typeof(Material))
                                   .FirstElementId();

            ElementId idGraphicsStyle = new FilteredElementCollector(doc)
                                        .OfClass(typeof(GraphicsStyle))
                                        .FirstElementId();

            builder.OpenConnectedFaceSet(true);

            FaceArray faceArray = transientSolid.Faces;

            foreach (Face face in faceArray)
            {
                List <XYZ> triFace = new List <XYZ>(3);
                Mesh       mesh    = face.Triangulate();

                if (null == mesh)
                {
                    continue;
                }

                int triCount = mesh.NumTriangles;

                for (int i = 0; i < triCount; i++)
                {
                    triFace.Clear();

                    for (int n = 0; n < 3; n++)
                    {
                        triFace.Add(mesh.get_Triangle(i).get_Vertex(n));
                    }

                    builder.AddFace(new TessellatedFace(triFace, idMaterial));
                }
            }

            builder.CloseConnectedFaceSet();

            // return builder.Build(TessellatedShapeBuilderTarget.Solid, TessellatedShapeBuilderFallback.Abort, idGraphicsStyle);
            return(builder.GetBuildResult().GetGeometricalObjects());
        }
Beispiel #12
0
        public List <PlanarFace> GetMeshedFaces()
        {
            Mesh mesh = GetMesh();
            TessellatedShapeBuilder builder
                = new TessellatedShapeBuilder();

            builder.OpenConnectedFaceSet(false);

            List <XYZ> args = new List <XYZ>(3);

            XYZ[] triangleCorners = new XYZ[3];

            for (int i = 0; i < mesh.NumTriangles; ++i)
            {
                MeshTriangle triangle = mesh.get_Triangle(i);

                triangleCorners[0] = triangle.get_Vertex(0);
                triangleCorners[1] = triangle.get_Vertex(1);
                triangleCorners[2] = triangle.get_Vertex(2);

                TessellatedFace tesseFace
                    = new TessellatedFace(triangleCorners,
                                          ElementId.InvalidElementId);

                if (builder.DoesFaceHaveEnoughLoopsAndVertices(
                        tesseFace))
                {
                    builder.AddFace(tesseFace);
                }
            }

            builder.CloseConnectedFaceSet();

            TessellatedShapeBuilderResult result
                = builder.Build(
                      TessellatedShapeBuilderTarget.AnyGeometry,
                      TessellatedShapeBuilderFallback.Mesh,
                      ElementId.InvalidElementId);

            var geo = result.GetGeometricalObjects();

            var solids = GeoHelper.GetSolidsInModel(geo, GeoHelper.SolidVolumnConstraint.Any);
            var faces  = GeoHelper.GetSurfaces(solids.Keys);

            return(faces.OfType <PlanarFace>().ToList());
        }
Beispiel #13
0
        private void Execute(IEnumerable <List <XYZ> > triangles)
        {
            void Run(Document doc)
            {
                TessellatedShapeBuilder builder = new TessellatedShapeBuilder();

                builder.OpenConnectedFaceSet(false);

                foreach (List <XYZ> triangle in triangles)
                {
                    TessellatedFace tessellatedFace = new TessellatedFace(triangle, ElementId.InvalidElementId);

                    if (builder.DoesFaceHaveEnoughLoopsAndVertices(tessellatedFace))
                    {
                        builder.AddFace(tessellatedFace);
                    }
                }

                builder.CloseConnectedFaceSet();
                builder.Target   = TessellatedShapeBuilderTarget.AnyGeometry;
                builder.Fallback = TessellatedShapeBuilderFallback.Mesh;
                builder.Build();

                TessellatedShapeBuilderResult result = builder.GetBuildResult();

                //var ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));

                //ds.ApplicationId = Assembly.GetExecutingAssembly().GetType().GUID.ToString();
                //ds.ApplicationDataId = Guid.NewGuid().ToString();
                //ds.Name = "NavisWorksShape";
                //DirectShapeOptions dsOptions = ds.GetOptions();
                //dsOptions.ReferencingOption = DirectShapeReferencingOption.Referenceable;
                //ds.SetOptions(dsOptions);

                //ds.SetShape(result.GetGeometricalObjects());
                CreateDirectShape(doc, result.GetGeometricalObjects());
            }

            _eventHandler.Action          = Run;
            _eventHandler.TransactionName = "Importing navisWorks elements";

            _externalEvent.Raise();
        }
        public static IList <GeometryObject> ToRevitType(this Autodesk.DesignScript.Geometry.Surface srf,
                                                         bool performHostUnitConversion = true)
        {
            var rp = new RenderPackage();

            if (performHostUnitConversion)
            {
                var newSrf = srf.InHostUnits();
                newSrf.Tessellate(rp);
                newSrf.Dispose();
            }
            else
            {
                srf.Tessellate(rp);
            }

            var tsb = new TessellatedShapeBuilder();

            tsb.OpenConnectedFaceSet(false);

            var v = rp.TriangleVertices;

            for (int i = 0; i < v.Count; i += 9)
            {
                var a = new XYZ(v[i], v[i + 1], v[i + 2]);
                var b = new XYZ(v[i + 3], v[i + 4], v[i + 5]);
                var c = new XYZ(v[i + 6], v[i + 7], v[i + 8]);

                var face = new TessellatedFace(new List <XYZ>()
                {
                    a, b, c
                }, MaterialsManager.Instance.DynamoMaterialId);
                tsb.AddFace(face);
            }

            tsb.CloseConnectedFaceSet();

            var result = tsb.Build(TessellatedShapeBuilderTarget.Mesh, TessellatedShapeBuilderFallback.Salvage, ElementId.InvalidElementId);

            return(result.GetGeometricalObjects());
        }
Beispiel #15
0
        /// <summary>
        /// Start collecting faces to create a BRep solid.
        /// </summary>
        public void StartCollectingFaceSet()
        {
            if (m_TessellatedShapeBuilder == null)
            {
                m_TessellatedShapeBuilder = new TessellatedShapeBuilder();
            }

            m_TessellatedShapeBuilder.OpenConnectedFaceSet(false);

            if (m_TessellatedFaceVertices != null)
            {
                m_TessellatedFaceVertices.Clear();
            }

            if (m_TessellatedFaceBoundary != null)
            {
                m_TessellatedFaceBoundary.Clear();
            }

            m_faceMaterialId = ElementId.InvalidElementId;
        }
Beispiel #16
0
        /// <summary>
        /// Stop collecting faces to create a BRep solid.
        /// </summary>
        public void StopCollectingFaceSet()
        {
            if (TessellatedShapeBuilder == null)
            {
                throw new InvalidOperationException("StartCollectingFaceSet has not been called.");
            }

            TessellatedShapeBuilder.CloseConnectedFaceSet();

            if (TessellatedFaceBoundary != null)
            {
                TessellatedFaceBoundary.Clear();
            }

            if (TessellatedFaceVertices != null)
            {
                TessellatedFaceVertices.Clear();
            }

            FaceMaterialId = ElementId.InvalidElementId;
        }
        /// <summary>
        /// this method converts a ProtoGeometry IndexGroup and Points to a Revit tessellated face, and adds it
        //  to the TessellatedShape Builder that is passed in.
        /// </summary>
        /// <param name="tsb">a Revit TessellatedShapeBuilder which we wish to add a face to </param>
        /// <param name="f"> a ProtoGeometry indexGroup defining a Mesh face</param>
        /// <param name="meshVerts">a vertex array of Points which should be the
        /// entire vertex array extracted from a ProtoGeometry Mesh.</param>
        /// <param name="performHostUnitConversion">a Bool which enables host unit conversion scaling</param>
        /// <param name="materialId">an ElementId represnting the Material we want to apply to this face</param>
        private static void AddFace(TessellatedShapeBuilder tsb,
                                    IndexGroup f,
                                    Autodesk.DesignScript.Geometry.Point[] meshVerts,
                                    bool performHostUnitConversion,
                                    ElementId materialId)
        {
            var xyzs           = new List <Autodesk.Revit.DB.XYZ>();
            var currentIndices = new List <uint>()
            {
                f.A, f.B, f.C, f.D
            };

            for (int i = 0; i < f.Count; i++)
            {
                var currentindex = Convert.ToInt32(currentIndices[i]);
                //convert all the points to Revit XYZ vectors and perform unit conversion here
                xyzs.Add(meshVerts[currentindex].ToXyz(performHostUnitConversion));
            }

            var face = new TessellatedFace(xyzs, materialId != null ? materialId : MaterialsManager.Instance.DynamoMaterialId);

            tsb.AddFace(face);
        }
Beispiel #18
0
        /// <summary>
        /// Create a geometry object(s) described by stored face sets, if possible.
        /// Usually a single-element IList conatining either Solid or Mesh is returned.
        /// A two-elemant IList containing a Solid as the 1st element and a Mesh as
        /// the 2nd is returned if while building multiple face sets, a fallback
        /// was used for some but not all sets.
        /// </summary>
        /// <returns>The IList created, or null. The IList can contain a Solid and/or a Mesh.
        /// If Solid is present, it always the 1st element.</returns>
        private IList <GeometryObject> CreateGeometryObjects(string guid,
                                                             out bool hasInvalidData, out TessellatedShapeBuilderOutcome outcome)
        {
            try
            {
                TessellatedShapeBuilder.CloseConnectedFaceSet();

                // The OwnerInfo is currently unused; the value doesn't really matter.
                TessellatedShapeBuilder.LogString  = IFCImportFile.TheFileName;
                TessellatedShapeBuilder.LogInteger = IFCImportFile.TheBrepCounter;
                TessellatedShapeBuilder.OwnerInfo  = guid != null ? guid : "Temporary Element";

                TessellatedShapeBuilder.Target          = TargetGeometry;
                TessellatedShapeBuilder.Fallback        = FallbackGeometry;
                TessellatedShapeBuilder.GraphicsStyleId = GraphicsStyleId;

                TessellatedShapeBuilder.Build();

                TessellatedShapeBuilderResult result = TessellatedShapeBuilder.GetBuildResult();

                // It is important that we clear the TSB after we build above, otherwise we will "collect" geometries
                // in the DirectShape and create huge files with redundant data.
                ClearTessellatedShapeBuilder();
                hasInvalidData = result.HasInvalidData;
                outcome        = result.Outcome;
                return(result.GetGeometricalObjects());
            }
            catch (Exception ex)
            {
                Importer.TheLog.LogError(CreatorId(), ex.Message, false);

                ClearTessellatedShapeBuilder();
                hasInvalidData = true;
                outcome        = TessellatedShapeBuilderOutcome.Nothing;
                return(null);
            }
        }
Beispiel #19
0
 private void ClearTessellatedShapeBuilder()
 {
     TessellatedShapeBuilder.Clear();
     CreatedFacesCount = 0;
 }
Beispiel #20
0
        /// <summary>
        /// Create a new DirectShape element from given
        /// list of faces and return the number of faces
        /// processed.
        /// Return -1 if a face vertex index exceeds the
        /// total number of available vertices,
        /// representing a fatal error.
        /// </summary>
        public static DirectShape NewDirectShape(
            //List<XYZ> vertices,
            Autodesk.DesignScript.Geometry.Mesh mesh,
            //FaceCollection faces,
            //UIDocument UIdoc,
            //ElementId graphicsStyleId,
            //string appGuid,
            string shapeName)
        {
            int nFaces       = 0;
            int nFacesFailed = 0;

            Document doc = DocumentManager.Instance.CurrentDBDocument;

            string appGuid = doc.Application.ActiveAddInId.GetGUID().ToString();

            // Retrieve "<Sketch>" graphics style,
            // if it exists.

            FilteredElementCollector collector
                = new FilteredElementCollector(doc)
                  .OfClass(typeof(GraphicsStyle));

            GraphicsStyle style
                = collector.Cast <GraphicsStyle>()
                  .FirstOrDefault <GraphicsStyle>(gs
                                                  => gs.Name.Equals("<Sketch>"));

            ElementId graphicsStyleId = null;

            if (style != null)
            {
                graphicsStyleId = style.Id;
            }


            TessellatedShapeBuilder builder
                = new TessellatedShapeBuilder();

            builder.LogString = shapeName;

            List <Autodesk.DesignScript.Geometry.Point> corners = new List <Autodesk.DesignScript.Geometry.Point>(4);
            List <XYZ> XYZcorners = new List <XYZ>(4);

            builder.OpenConnectedFaceSet(false);

            // foreach (Face f in faces)
            //{
            builder.LogInteger = nFaces;

            if (corners.Capacity < mesh.FaceIndices.Length)
            {
                corners    = new List <Autodesk.DesignScript.Geometry.Point>(mesh.FaceIndices.Length);
                XYZcorners = new List <XYZ>(mesh.FaceIndices.Length);
            }

            corners.Clear();
            XYZcorners.Clear();

            foreach (IndexGroup i in mesh.FaceIndices)
            {
                //Debug.Assert(vertices.Count > i.vertex,
                //  "how can the face vertex index be larger "
                //  + "than the total number of vertices?");

                corners.Add(mesh.VertexPositions[i.A]);
                XYZcorners.Add(new XYZ(mesh.VertexPositions[(int)i.A].X, mesh.VertexPositions[(int)i.A].Y,
                                       mesh.VertexPositions[(int)i.A].Z));
                corners.Add(mesh.VertexPositions[(int)i.B]);
                XYZcorners.Add(new XYZ(mesh.VertexPositions[(int)i.B].X, mesh.VertexPositions[(int)i.B].Y,
                                       mesh.VertexPositions[(int)i.B].Z));
                corners.Add(mesh.VertexPositions[(int)i.C]);
                XYZcorners.Add(new XYZ(mesh.VertexPositions[(int)i.C].X, mesh.VertexPositions[(int)i.C].Y,
                                       mesh.VertexPositions[(int)i.C].Z));

                if (i.Count > 3)
                {
                    corners.Add(mesh.VertexPositions[(int)i.D]);
                    XYZcorners.Add(new XYZ(mesh.VertexPositions[(int)i.D].X, mesh.VertexPositions[(int)i.D].Y,
                                           mesh.VertexPositions[(int)i.D].Z));
                }
            }



            try
            {
                builder.AddFace(new TessellatedFace(XYZcorners,
                                                    ElementId.InvalidElementId));

                ++nFaces;
            }
            catch (Autodesk.Revit.Exceptions.ArgumentException ex)
            {
                // Remember something went wrong here.

                ++nFacesFailed;

                Debug.Print(
                    "Revit API argument exception {0}\r\n"
                    + "Failed to add face with {1} corners: {2}",
                    ex.Message, corners.Count,
                    string.Join(", ",
                                XYZcorners.Select <XYZ, string>(
                                    p => Util.PointString(p))));
            }
            //}

            builder.CloseConnectedFaceSet();

            // Refer to StlImport sample for more clever
            // handling of target and fallback and the
            // possible combinations.

            TessellatedShapeBuilderResult r
                = builder.Build(
                      TessellatedShapeBuilderTarget.Mesh,
                      TessellatedShapeBuilderFallback.Salvage,
                      graphicsStyleId);

            ConversionLog myLog = new ConversionLog("c:\\conversionLogFileName.txt");

            DataConversionMonitorScope myLoggingScope = new DataConversionMonitorScope(myLog);

            TessellatedShapeBuilderOutcome testOutcome = r.Outcome;
            IList <GeometryObject>         test        = r.GetGeometricalObjects();


            try
            {
                TransactionManager.Instance.EnsureInTransaction(DocumentManager.Instance.CurrentDBDocument);

                DirectShape ds = DirectShape.CreateElement(
                    doc, _categoryId, appGuid, shapeName);

                ds.SetShape(r.GetGeometricalObjects());
                ds.Name = shapeName;

                Debug.Print(
                    "Shape '{0}': added {1} face{2}, {3} face{4} failed.",
                    shapeName, nFaces, Util.PluralSuffix(nFaces),
                    nFacesFailed, Util.PluralSuffix(nFacesFailed));

                TransactionManager.Instance.TransactionTaskDone();

                return(ds);
            }
            catch (Exception ex)
            {
                Debug.Print(
                    "Problem with adding DirectShape: " + ex.Message.ToString());

                return(null);
            }
        }
Beispiel #21
0
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            // Note that lcs is unused.

            if (XLength < MathUtil.Eps() || YLength < MathUtil.Eps() || ZLength < MathUtil.Eps())
            {
                return(null);
            }

            Transform scaledExtrusionPosition = (scaledLcs == null) ? Transform.Identity : scaledLcs;

            XYZ llPoint = scaledExtrusionPosition.OfPoint(XYZ.Zero);
            XYZ lrPoint = scaledExtrusionPosition.OfPoint(new XYZ(XLength, 0, 0));
            XYZ urPoint = scaledExtrusionPosition.OfPoint(new XYZ(XLength, YLength, 0));
            XYZ ulPoint = scaledExtrusionPosition.OfPoint(new XYZ(0, YLength, 0));

            CurveLoop outerLoop = new CurveLoop();

            outerLoop.Append(Line.CreateBound(llPoint, lrPoint));
            outerLoop.Append(Line.CreateBound(lrPoint, urPoint));
            outerLoop.Append(Line.CreateBound(urPoint, ulPoint));
            outerLoop.Append(Line.CreateBound(ulPoint, llPoint));

            IList <CurveLoop> loops = new List <CurveLoop>();

            loops.Add(outerLoop);

            XYZ          scaledExtrusionDirection = scaledExtrusionPosition.OfVector(XYZ.BasisZ);
            SolidOptions solidOptions             = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);

            GeometryObject block = null;

            try
            {
                block = GeometryCreationUtilities.CreateExtrusionGeometry(loops, scaledExtrusionDirection, ZLength, solidOptions);
            }
            catch (Exception ex)
            {
                if (shapeEditScope.MustCreateSolid())
                {
                    throw ex;
                }

                Importer.TheLog.LogError(Id, "Block has an invalid definition for a solid; reverting to mesh.", false);

                MeshFromGeometryOperationResult meshResult = TessellatedShapeBuilder.CreateMeshByExtrusion(
                    loops, scaledExtrusionDirection, ZLength, GetMaterialElementId(shapeEditScope));

                // will throw if mesh is not available
                block = meshResult.GetMesh();
            }

            IList <GeometryObject> blocks = new List <GeometryObject>();

            if (block != null)
            {
                blocks.Add(block);
            }

            return(blocks);
        }
        public static void Execute1( 
            ExternalCommandData commandData)
        {
            Transaction trans = null;

              UIDocument uidoc = commandData.Application
            .ActiveUIDocument;

              Document doc = uidoc.Document;

              try
              {
            Selection choices = uidoc.Selection;

            Reference reference = choices.PickObject(
              ObjectType.Face );

            Element el = doc.GetElement(
              reference.ElementId );

            trans = new Transaction( doc, "Create elements" );
            trans.Start();

            TessellatedShapeBuilder builder
              = new TessellatedShapeBuilder();

            builder.OpenConnectedFaceSet( false );

            Face face = el.GetGeometryObjectFromReference(
              reference ) as Face;

            Mesh mesh = face.Triangulate();
            List<XYZ> args = new List<XYZ>( 3 );

            XYZ offset = new XYZ();
            if( el.Location is LocationPoint )
            {
              LocationPoint locationPoint = el.Location
            as LocationPoint;
              offset = locationPoint.Point;
            }

            for( int i = 0; i < mesh.NumTriangles; i++ )
            {
              MeshTriangle triangle = mesh.get_Triangle(
            i );

              XYZ p1 = triangle.get_Vertex( 0 );
              XYZ p2 = triangle.get_Vertex( 1 );
              XYZ p3 = triangle.get_Vertex( 2 );

              p1 = p1.Add( offset );
              p2 = p2.Add( offset );
              p3 = p3.Add( offset );

              args.Clear();
              args.Add( p1 );
              args.Add( p2 );
              args.Add( p3 );

              TessellatedFace tesseFace
            = new TessellatedFace( args,
              ElementId.InvalidElementId );

              if( builder.DoesFaceHaveEnoughLoopsAndVertices(
            tesseFace ) )
              {
            builder.AddFace( tesseFace );
              }
            }

            builder.CloseConnectedFaceSet();

            TessellatedShapeBuilderResult result
              = builder.Build(
            TessellatedShapeBuilderTarget.AnyGeometry,
            TessellatedShapeBuilderFallback.Mesh,
            ElementId.InvalidElementId );

            ElementId categoryId = new ElementId(
              BuiltInCategory.OST_GenericModel );

            DirectShape ds = DirectShape.CreateElement(
              doc, categoryId,
              Assembly.GetExecutingAssembly().GetType()
              .GUID.ToString(), Guid.NewGuid().ToString() );

            ds.SetShape( result.GetGeometricalObjects() );

            ds.Name = "MyShape";

            trans.Commit();
              }
              catch( Exception ex )
              {
            if( trans != null )
              trans.RollBack();

            Debug.Print( ex.Message );
              }
        }
Beispiel #23
0
        /// <summary>
        /// Create a new DirectShape element from given
        /// list of faces and return the number of faces
        /// processed.
        /// Return -1 if a face vertex index exceeds the
        /// total number of available vertices, 
        /// representing a fatal error.
        /// </summary>
        static int NewDirectShape(
            List<XYZ> vertices,
            FaceCollection faces,
            Document doc,
            ElementId graphicsStyleId,
            string appGuid,
            string shapeName)
        {
            int nFaces = 0;
              int nFacesFailed = 0;

              TessellatedShapeBuilder builder
            = new TessellatedShapeBuilder();

              builder.LogString = shapeName;

              List<XYZ> corners = new List<XYZ>( 4 );

              builder.OpenConnectedFaceSet( false );

              foreach( Face f in faces )
              {
            builder.LogInteger = nFaces;

            if( corners.Capacity < f.Indices.Count )
            {
              corners = new List<XYZ>( f.Indices.Count );
            }

            corners.Clear();

            foreach( Index i in f.Indices )
            {
              Debug.Assert( vertices.Count > i.vertex,
            "how can the face vertex index be larger "
            + "than the total number of vertices?" );

              if( i.vertex >= vertices.Count )
              {
            return -1;
              }
              corners.Add( vertices[i.vertex] );
            }

            try
            {
              builder.AddFace( new TessellatedFace( corners,
            ElementId.InvalidElementId ) );

              ++nFaces;
            }
            catch( Autodesk.Revit.Exceptions.ArgumentException ex )
            {
              // Remember something went wrong here.

              ++nFacesFailed;

              Debug.Print(
            "Revit API argument exception {0}\r\n"
            + "Failed to add face with {1} corners: {2}",
            ex.Message, corners.Count,
            string.Join( ", ",
              corners.Select<XYZ, string>(
                p => Util.PointString( p ) ) ) );
            }
              }
              builder.CloseConnectedFaceSet();

              // Refer to StlImport sample for more clever
              // handling of target and fallback and the
              // possible combinations.

              TessellatedShapeBuilderResult r
            = builder.Build(
              TessellatedShapeBuilderTarget.AnyGeometry,
              TessellatedShapeBuilderFallback.Mesh,
              graphicsStyleId );

              DirectShape ds = DirectShape.CreateElement(
            doc, _categoryId, appGuid, shapeName );

              ds.SetShape( r.GetGeometricalObjects() );
              ds.Name = shapeName;

              Debug.Print(
            "Shape '{0}': added {1} face{2}, {3} face{4} failed.",
            shapeName, nFaces, Util.PluralSuffix( nFaces ),
            nFacesFailed, Util.PluralSuffix( nFacesFailed ) );

              return nFaces;
        }
        /// <summary>
        /// Create a new list of geometry objects from the
        /// given input. As input, we supply the result of
        /// Room.GetClosedShell. The output is the exact
        /// same solid lacking whatever flaws are present
        /// in the input solid.
        /// </summary>
        static IList <GeometryObject> CopyGeometry(
            GeometryElement geo,
            ElementId materialId,
            List <IntPoint3d> coords,
            List <TriangleIndices> indices)
        {
            TessellatedShapeBuilderResult result = null;

            TessellatedShapeBuilder builder
                = new TessellatedShapeBuilder();

            // Need to include the key in the value, otherwise
            // no way to access it later, cf.
            // https://stackoverflow.com/questions/1619090/getting-a-keyvaluepair-directly-from-a-dictionary

            Dictionary <XYZ, KeyValuePair <XYZ, int> > pts
                = new Dictionary <XYZ, KeyValuePair <XYZ, int> >(
                      new XyzEqualityComparer());

            int nSolids = 0;
            //int nFaces = 0;
            int nTriangles = 0;
            //int nVertices = 0;
            List <XYZ> vertices = new List <XYZ>(3);

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

                if (null != solid)
                {
                    if (0 < solid.Volume)
                    {
                        ++nSolids;

                        builder.OpenConnectedFaceSet(false);

                        #region Create a new solid based on tessellation of the invalid room closed shell solid
#if CREATE_NEW_SOLID_USING_TESSELATION
                        Debug.Assert(
                            SolidUtils.IsValidForTessellation(solid),
                            "expected a valid solid for room closed shell");

                        SolidOrShellTessellationControls controls
                            = new SolidOrShellTessellationControls()
                            {
                            //
                            // Summary:
                            //     A positive real number specifying how accurately a triangulation should approximate
                            //     a solid or shell.
                            //
                            // Exceptions:
                            //   T:Autodesk.Revit.Exceptions.ArgumentOutOfRangeException:
                            //     When setting this property: The given value for accuracy must be greater than
                            //     0 and no more than 30000 feet.
                            // This statement is not true. I set Accuracy = 0.003 and an exception was thrown.
                            // Setting it to 0.006 was acceptable. 0.03 is a bit over 9 mm.
                            //
                            // Remarks:
                            //     The maximum distance from a point on the triangulation to the nearest point on
                            //     the solid or shell should be no greater than the specified accuracy. This constraint
                            //     may be approximately enforced.
                            Accuracy = 0.03,
                            //
                            // Summary:
                            //     An number between 0 and 1 (inclusive) specifying the level of detail for the
                            //     triangulation of a solid or shell.
                            //
                            // Exceptions:
                            //   T:Autodesk.Revit.Exceptions.ArgumentOutOfRangeException:
                            //     When setting this property: The given value for levelOfDetail must lie between
                            //     0 and 1 (inclusive).
                            //
                            // Remarks:
                            //     Smaller values yield coarser triangulations (fewer triangles), while larger values
                            //     yield finer triangulations (more triangles).
                            LevelOfDetail = 0.1,
                            //
                            // Summary:
                            //     A non-negative real number specifying the minimum allowed angle for any triangle
                            //     in the triangulation, in radians.
                            //
                            // Exceptions:
                            //   T:Autodesk.Revit.Exceptions.ArgumentOutOfRangeException:
                            //     When setting this property: The given value for minAngleInTriangle must be at
                            //     least 0 and less than 60 degrees, expressed in radians. The value 0 means to
                            //     ignore the minimum angle constraint.
                            //
                            // Remarks:
                            //     A small value can be useful when triangulating long, thin objects, in order to
                            //     keep the number of triangles small, but it can result in long, thin triangles,
                            //     which are not acceptable for all applications. If the value is too large, this
                            //     constraint may not be satisfiable, causing the triangulation to fail. This constraint
                            //     may be approximately enforced. A value of 0 means to ignore the minimum angle
                            //     constraint.
                            MinAngleInTriangle = 3 * Math.PI / 180.0,
                            //
                            // Summary:
                            //     A positive real number specifying the minimum allowed value for the external
                            //     angle between two adjacent triangles, in radians.
                            //
                            // Exceptions:
                            //   T:Autodesk.Revit.Exceptions.ArgumentOutOfRangeException:
                            //     When setting this property: The given value for minExternalAngleBetweenTriangles
                            //     must be greater than 0 and no more than 30000 feet.
                            //
                            // Remarks:
                            //     A small value yields more smoothly curved triangulated surfaces, usually at the
                            //     expense of an increase in the number of triangles. Note that this setting has
                            //     no effect for planar surfaces. This constraint may be approximately enforced.
                            MinExternalAngleBetweenTriangles = 0.2 * Math.PI
                            };

                        TriangulatedSolidOrShell shell
                            = SolidUtils.TessellateSolidOrShell(solid, controls);

                        int n = shell.ShellComponentCount;

                        Debug.Assert(1 == n,
                                     "expected just one shell component in room closed shell");

                        TriangulatedShellComponent component
                            = shell.GetShellComponent(0);

                        int coordsBase  = coords.Count;
                        int indicesBase = indices.Count;

                        n = component.VertexCount;

                        for (int i = 0; i < n; ++i)
                        {
                            XYZ v = component.GetVertex(i);
                            coords.Add(new IntPoint3d(v));
                        }

                        n = component.TriangleCount;

                        for (int i = 0; i < n; ++i)
                        {
                            TriangleInShellComponent t
                                = component.GetTriangle(i);

                            vertices.Clear();

                            vertices.Add(component.GetVertex(t.VertexIndex0));
                            vertices.Add(component.GetVertex(t.VertexIndex1));
                            vertices.Add(component.GetVertex(t.VertexIndex2));

                            indices.Add(new TriangleIndices(
                                            coordsBase + t.VertexIndex0,
                                            coordsBase + t.VertexIndex1,
                                            coordsBase + t.VertexIndex2));

                            TessellatedFace tf = new TessellatedFace(
                                vertices, materialId);

                            if (builder.DoesFaceHaveEnoughLoopsAndVertices(tf))
                            {
                                builder.AddFace(tf);
                                ++nTriangles;
                            }
                        }
#else
                        // Iterate over the individual solid faces

                        foreach (Face f in solid.Faces)
                        {
                            vertices.Clear();

                            #region Use face triangulation
#if USE_FACE_TRIANGULATION
                            Mesh mesh = f.Triangulate();
                            int  n    = mesh.NumTriangles;

                            for (int i = 0; i < n; ++i)
                            {
                                MeshTriangle triangle = mesh.get_Triangle(i);

                                XYZ p1 = triangle.get_Vertex(0);
                                XYZ p2 = triangle.get_Vertex(1);
                                XYZ p3 = triangle.get_Vertex(2);

                                vertices.Clear();
                                vertices.Add(p1);
                                vertices.Add(p2);
                                vertices.Add(p3);

                                TessellatedFace tf
                                    = new TessellatedFace(
                                          vertices, materialId);

                                if (builder.DoesFaceHaveEnoughLoopsAndVertices(tf))
                                {
                                    builder.AddFace(tf);
                                    ++nTriangles;
                                }
                            }
#endif // USE_FACE_TRIANGULATION
                            #endregion // Use face triangulation

                            #region Use original solid and its EdgeLoops
#if USE_EDGELOOPS
                            // This returns arbitrarily ordered and
                            // oriented edges, so no solid can be
                            // generated.

                            foreach (EdgeArray loop in f.EdgeLoops)
                            {
                                foreach (Edge e in loop)
                                {
                                    XYZ p = e.AsCurve().GetEndPoint(0);
                                    XYZ q = p;

                                    if (pts.ContainsKey(p))
                                    {
                                        KeyValuePair <XYZ, int> kv = pts[p];
                                        q = kv.Key;
                                        int n = kv.Value;
                                        pts[p] = new KeyValuePair <XYZ, int>(
                                            q, ++n);

                                        Debug.Print("Ignoring vertex at {0} "
                                                    + "with distance {1} to existing "
                                                    + "vertex {2}",
                                                    p, p.DistanceTo(q), q);
                                    }
                                    else
                                    {
                                        pts[p] = new KeyValuePair <XYZ, int>(
                                            p, 1);
                                    }

                                    vertices.Add(q);
                                    ++nVertices;
                                }
                            }
#endif // USE_EDGELOOPS
                            #endregion // Use original solid and its EdgeLoops

                            #region Use original solid and GetEdgesAsCurveLoops
#if USE_AS_CURVE_LOOPS
                            // The solids generated by this have some weird
                            // normals, so they do not render correctly in
                            // the Forge viewer. Revert to triangles again.

                            IList <CurveLoop> loops
                                = f.GetEdgesAsCurveLoops();

                            foreach (CurveLoop loop in loops)
                            {
                                foreach (Curve c in loop)
                                {
                                    XYZ p = c.GetEndPoint(0);
                                    XYZ q = p;

                                    if (pts.ContainsKey(p))
                                    {
                                        KeyValuePair <XYZ, int> kv = pts[p];
                                        q = kv.Key;
                                        int n = kv.Value;
                                        pts[p] = new KeyValuePair <XYZ, int>(
                                            q, ++n);

                                        Debug.Print("Ignoring vertex at {0} "
                                                    + "with distance {1} to existing "
                                                    + "vertex {2}",
                                                    p, p.DistanceTo(q), q);
                                    }
                                    else
                                    {
                                        pts[p] = new KeyValuePair <XYZ, int>(
                                            p, 1);
                                    }

                                    vertices.Add(q);
                                    ++nVertices;
                                }
                            }
#endif // USE_AS_CURVE_LOOPS
                            #endregion // Use original solid and GetEdgesAsCurveLoops

                            builder.AddFace(new TessellatedFace(
                                                vertices, materialId));

                            ++nFaces;
                        }
#endif // CREATE_NEW_SOLID_USING_TESSELATION
                        #endregion // Create a new solid based on tessellation of the invalid room closed shell solid

                        builder.CloseConnectedFaceSet();
                        builder.Target   = TessellatedShapeBuilderTarget.AnyGeometry; // Solid failed
                        builder.Fallback = TessellatedShapeBuilderFallback.Mesh;      // use Abort if target is Solid
                        builder.Build();
                        result = builder.GetBuildResult();

                        // Debug printout log of current solid's glTF facet data

                        n = coords.Count - coordsBase;

                        Debug.Print("{0} glTF vertex coordinates "
                                    + "in millimetres:", n);

                        Debug.Print(string.Join(" ", coords
                                                .TakeWhile <IntPoint3d>((p, i) => coordsBase <= i)
                                                .Select <IntPoint3d, string>(p => p.ToString())));

                        n = indices.Count - indicesBase;

                        Debug.Print("{0} glTF triangles:", n);

                        Debug.Print(string.Join(" ", indices
                                                .TakeWhile <TriangleIndices>((ti, i) => indicesBase <= i)
                                                .Select <TriangleIndices, string>(ti => ti.ToString())));
                    }
                }
            }
            return(result.GetGeometricalObjects());
        }
Beispiel #25
0
        // Create a pyramid-shaped DirectShape using given material for the faces
        static public void CreateTessellatedShape(Document doc, ElementId materialId)
        {
            List <XYZ> loopVertices = new List <XYZ>(4);

            TessellatedShapeBuilder builder = new TessellatedShapeBuilder();

            builder.OpenConnectedFaceSet(true);
            // create a pyramid with a square base 4' x 4' and 5' high
            double length = 4.0;
            double height = 5.0;

            XYZ basePt1 = XYZ.Zero;
            XYZ basePt2 = new XYZ(length, 0, 0);
            XYZ basePt3 = new XYZ(length, length, 0);
            XYZ basePt4 = new XYZ(0, length, 0);
            XYZ apex    = new XYZ(length / 2, length / 2, height);

            loopVertices.Add(basePt1);
            loopVertices.Add(basePt2);
            loopVertices.Add(basePt3);
            loopVertices.Add(basePt4);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(basePt1);
            loopVertices.Add(apex);
            loopVertices.Add(basePt2);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(basePt2);
            loopVertices.Add(apex);
            loopVertices.Add(basePt3);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(basePt3);
            loopVertices.Add(apex);
            loopVertices.Add(basePt4);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(basePt4);
            loopVertices.Add(apex);
            loopVertices.Add(basePt1);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            builder.CloseConnectedFaceSet();
            builder.Target   = TessellatedShapeBuilderTarget.Solid;
            builder.Fallback = TessellatedShapeBuilderFallback.Abort;
            builder.Build();

            TessellatedShapeBuilderResult result = builder.GetBuildResult();

            using (Transaction t = new Transaction(doc, "Create tessellated direct shape"))
            {
                t.Start();

                DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
                ds.ApplicationId     = "Application id";
                ds.ApplicationDataId = "Geometry object id";

                ds.SetShape(result.GetGeometricalObjects());
                t.Commit();
            }
        }
Beispiel #26
0
        private static IList <GeometryObject> GetGeometryObjectsFromFace(Face face)
        {
            IList <GeometryObject> shapeGeometries = null;

            try
            {
                List <CurveLoop> profiles = new List <CurveLoop>();
                XYZ normal = face.ComputeNormal(new UV(0, 0));

                IList <CurveLoop>          curveLoops       = face.GetEdgesAsCurveLoops();
                IList <IList <CurveLoop> > sortedCurveLoops = ExporterIFCUtils.SortCurveLoops(curveLoops);
                foreach (IList <CurveLoop> curveLoopList in sortedCurveLoops)
                {
                    foreach (CurveLoop curveLoop in curveLoopList)
                    {
                        if (curveLoop.IsCounterclockwise(normal))
                        {
                            profiles.Insert(0, curveLoop);
                        }
                        else
                        {
                            profiles.Add(curveLoop);
                        }
                    }
                }

                List <List <XYZ> > allLoopVertices = new List <List <XYZ> >();
                for (int i = 0; i < profiles.Count; i++)
                {
                    List <XYZ> vertices  = new List <XYZ>();
                    CurveLoop  curveLoop = profiles[i];
                    foreach (Curve curve in curveLoop)
                    {
                        IList <XYZ> tessellatedVertices = curve.Tessellate();
                        tessellatedVertices.RemoveAt(tessellatedVertices.Count - 1);
                        vertices.AddRange(tessellatedVertices);
                    }
                    allLoopVertices.Add(vertices);
                }

                TessellatedShapeBuilder builder = new TessellatedShapeBuilder();
                builder.OpenConnectedFaceSet(false);

                TessellatedFace tesseFace = new TessellatedFace(allLoopVertices.ToArray(), ElementId.InvalidElementId);
                if (builder.DoesFaceHaveEnoughLoopsAndVertices(tesseFace))
                {
                    builder.AddFace(tesseFace);
                }

                builder.CloseConnectedFaceSet();
#if RELEASE2015 || RELEASE2016
                TessellatedShapeBuilderResult result = builder.Build(TessellatedShapeBuilderTarget.AnyGeometry, TessellatedShapeBuilderFallback.Mesh, ElementId.InvalidElementId);
#else
                builder.Target   = TessellatedShapeBuilderTarget.AnyGeometry;
                builder.Fallback = TessellatedShapeBuilderFallback.Mesh;
                builder.Build();
                TessellatedShapeBuilderResult result = builder.GetBuildResult();
#endif
                shapeGeometries = result.GetGeometricalObjects();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to get geometry objects from a face.\n" + ex.Message, "Get Geometry Objects", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            return(shapeGeometries);
        }
        public static void CreateCube(Document doc, XYZ min, XYZ max, string name)
        {
            List <XYZ> loopVertices = new List <XYZ>(4);

            TessellatedShapeBuilder builder = new TessellatedShapeBuilder();

            builder.OpenConnectedFaceSet(true);

            XYZ topLeftBack     = new XYZ(min.X, max.Y, min.Z);
            XYZ topRightBack    = new XYZ(max.X, max.Y, min.Z);
            XYZ bottomLeftBack  = new XYZ(min.X, min.Y, min.Z); //min
            XYZ bottomRightBack = new XYZ(max.X, min.Y, min.Z);

            XYZ topLeftFront     = new XYZ(min.X, max.Y, max.Z);
            XYZ topRightFront    = new XYZ(max.X, max.Y, max.Z); //max
            XYZ bottomLeftFront  = new XYZ(min.X, min.Y, max.Z);
            XYZ bottomRightFront = new XYZ(max.X, min.Y, max.Z);


            //Create the material
            ElementId materialId = ElementId.InvalidElementId;

            loopVertices.Add(topLeftBack);
            loopVertices.Add(topRightBack);
            loopVertices.Add(topRightFront);
            loopVertices.Add(topLeftFront);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(bottomLeftBack);
            loopVertices.Add(bottomRightBack);
            loopVertices.Add(bottomRightFront);
            loopVertices.Add(bottomLeftFront);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(topLeftBack);
            loopVertices.Add(topLeftFront);
            loopVertices.Add(bottomLeftFront);
            loopVertices.Add(bottomLeftBack);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(topLeftBack);
            loopVertices.Add(topLeftFront);
            loopVertices.Add(bottomRightFront);
            loopVertices.Add(bottomRightBack);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(topLeftBack);
            loopVertices.Add(topRightBack);
            loopVertices.Add(bottomRightBack);
            loopVertices.Add(bottomLeftBack);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            loopVertices.Clear();
            loopVertices.Add(topLeftFront);
            loopVertices.Add(topRightFront);
            loopVertices.Add(bottomRightFront);
            loopVertices.Add(bottomLeftFront);
            builder.AddFace(new TessellatedFace(loopVertices, materialId));

            builder.CloseConnectedFaceSet();

            builder.Build();
            TessellatedShapeBuilderResult result = builder.GetBuildResult();

            using (Transaction t = new Transaction(doc, "Create tessellated direct shape"))
            {
                t.Start();

                DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
                ds.Name = name;
                ds.SetShape(result.GetGeometricalObjects());
                t.Commit();
            }
        }
        /// <summary>
        /// Start collecting faces to create a BRep solid.
        /// </summary>
        public void StartCollectingFaceSet()
        {
            if (m_TessellatedShapeBuilder == null)
                m_TessellatedShapeBuilder = new TessellatedShapeBuilder();

            m_TessellatedShapeBuilder.OpenConnectedFaceSet(false);

            if (m_TessellatedFaceVertices != null)
                m_TessellatedFaceVertices.Clear();

            if (m_TessellatedFaceBoundary != null)
                m_TessellatedFaceBoundary.Clear();

            m_faceMaterialId = ElementId.InvalidElementId;
        }
        static internal IEnumerable <GeometryObject> Convert(IEnumerable <Rhino.Geometry.Mesh> meshes)
        {
            List <XYZ> faceVertices = new List <XYZ>(4);

            var builder = new TessellatedShapeBuilder();

            builder.Target   = TessellatedShapeBuilderTarget.AnyGeometry;
            builder.Fallback = TessellatedShapeBuilderFallback.Mesh;

            foreach (var mesh in meshes)
            {
                Rhino.Geometry.Mesh[] pieces = mesh.DisjointMeshCount > 1 ?
                                               mesh.SplitDisjointPieces() :
                                               new Rhino.Geometry.Mesh[] { mesh };

                foreach (var piece in pieces)
                {
                    // Meshes with edges smaller than AbsoluteRevitTolerance (1/16 inch) are not welcome in Revit
                    while (piece.CollapseFacesByEdgeLength(false, ModelAbsoluteTolerance) > 0)
                    {
                        ;
                    }

                    piece.Faces.ConvertNonPlanarQuadsToTriangles(RhinoMath.ZeroTolerance, RhinoMath.UnsetValue, 5);

                    bool isOriented  = false;
                    bool hasBoundary = false;
                    bool isSolid     = piece.IsClosed && piece.IsManifold(true, out isOriented, out hasBoundary) && isOriented;
                    var  vertices    = piece.Vertices;

                    builder.OpenConnectedFaceSet(isSolid);
                    foreach (var face in piece.Faces)
                    {
                        faceVertices.Add(Convert(vertices[face.A]));
                        faceVertices.Add(Convert(vertices[face.B]));
                        faceVertices.Add(Convert(vertices[face.C]));
                        if (face.IsQuad)
                        {
                            faceVertices.Add(Convert(vertices[face.D]));
                        }

                        builder.AddFace(new TessellatedFace(faceVertices, ElementId.InvalidElementId));
                        faceVertices.Clear();
                    }
                    builder.CloseConnectedFaceSet();
                }
            }

            try
            {
                builder.Build();
            }
            catch (Autodesk.Revit.Exceptions.ApplicationException e)
            {
                Debug.Fail(e.Source, e.Message);
                return(null);
            }

            TessellatedShapeBuilderResult result = builder.GetBuildResult();

            return(result.GetGeometricalObjects());
        }
        //This method forked from: //https://github.com/jeremytammik/DirectObjLoader
        /// <summary>
        /// Create a new DirectShape element from given
        /// list of faces and return the number of faces
        /// processed.
        /// Return -1 if a face vertex index exceeds the
        /// total number of available vertices, 
        /// representing a fatal error.
        /// </summary>
        static int NewDirectShape(
            Autodesk.DesignScript.Geometry.Point[] vertices,
            IndexGroup[] faces,
            Document doc,
            ElementId graphicsStyleId,
            ElementId materialId,
            string appGuid,
            string shapeName)
        {
            int nFaces = 0;
            int nFacesFailed = 0;

            TessellatedShapeBuilder builder
              = new TessellatedShapeBuilder();

            //builder.LogString = shapeName;

            var corners = new List<Autodesk.DesignScript.Geometry.Point>();

            builder.OpenConnectedFaceSet(false);

            foreach (IndexGroup f in faces)
            {
               // builder.LogInteger = nFaces;

                corners.Clear();
                var indicies = new List<uint>() { f.A, f.B, f.C, f.D };
                for (int i = 0; i < f.Count; i++)
                {
                    var currentindex = Convert.ToInt32(indicies[i]);
                    //Debug.Assert(vertices.Length > currentindex,
                     // "how can the face vertex index be larger "
                     // + "than the total number of vertices?");

                 //   if (currentindex >= vertices.Length)
                  //  {
                  //      return -1;
                  //  }
                    corners.Add(vertices[currentindex]);
                }

                //convert all the points to Revit XYZ vectors
                var xyzs = corners.Select(x => x.ToXyz()).ToList();

                try
                {

                    builder.AddFace(new TessellatedFace(xyzs,
                      materialId));

                    ++nFaces;
                }
                catch (Autodesk.Revit.Exceptions.ArgumentException ex)
                {
                    // Remember something went wrong here.

                    ++nFacesFailed;

                    Debug.Print(
                      "Revit API argument exception {0}\r\n"
                      + "Failed to add face with {1} corners: {2}",
                      ex.Message, corners.Count,
                      string.Join(", ",
                        corners));
                }
            }
            builder.CloseConnectedFaceSet();

            // Refer to StlImport sample for more clever
            // handling of target and fallback and the
            // possible combinations.

            TessellatedShapeBuilderResult r
              = builder.Build(
                TessellatedShapeBuilderTarget.Mesh,
                TessellatedShapeBuilderFallback.Salvage,
                graphicsStyleId);

            var ds = Autodesk.Revit.DB.DirectShape.CreateElement(
              doc, _categoryId, appGuid, shapeName);

            ds.SetShape(r.GetGeometricalObjects());
            ds.Name = shapeName;

            //Debug.Print(
              //"Shape '{0}': added {1} faces, faces{2} failed.",
              //shapeName, nFaces,
              //nFacesFailed);

            return nFaces;
        }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>One or more created geometries.</returns>
        /// <remarks>The scaledLcs is only partially supported in this routine; it allows scaling the depth of the extrusion,
        /// which is commonly found in ACA files.</remarks>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            if (Direction == null)
            {
                Importer.TheLog.LogError(Id, "Error processing IfcExtrudedAreaSolid, can't create geometry.", false);
                return(null);
            }

            Transform origLCS       = (lcs == null) ? Transform.Identity : lcs;
            Transform origScaledLCS = (scaledLcs == null) ? Transform.Identity : scaledLcs;

            Transform extrusionPosition       = (Position == null) ? origLCS : origLCS.Multiply(Position);
            Transform scaledExtrusionPosition = (Position == null) ? origScaledLCS : origScaledLCS.Multiply(Position);

            XYZ extrusionDirection = extrusionPosition.OfVector(Direction);

            ISet <IList <CurveLoop> > disjointLoops = GetTransformedCurveLoops(extrusionPosition);

            if (disjointLoops == null || disjointLoops.Count() == 0)
            {
                return(null);
            }

            IList <GeometryObject> extrusions = new List <GeometryObject>();

            foreach (IList <CurveLoop> loops in disjointLoops)
            {
                SolidOptions solidOptions    = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
                XYZ          scaledDirection = scaledExtrusionPosition.OfVector(Direction);
                double       currDepth       = Depth * scaledDirection.GetLength();

                GeometryObject extrusionObject = null;
                try
                {
                    // We may try to create separate extrusions, one per layer here.
                    bool      shouldWarn                   = false;
                    ElementId overrideMaterialId           = ElementId.InvalidElementId;
                    IList <GeometryObject> extrusionLayers = CreateGeometryFromMaterialLayerUsage(shapeEditScope, extrusionPosition, loops,
                                                                                                  extrusionDirection, currDepth, out overrideMaterialId, out shouldWarn);

                    if (extrusionLayers == null || extrusionLayers.Count == 0)
                    {
                        if (shouldWarn)
                        {
                            Importer.TheLog.LogWarning(Id, "Couldn't process associated IfcMaterialLayerSetUsage, using body geometry instead.", false);
                        }
                        if (overrideMaterialId != ElementId.InvalidElementId)
                        {
                            solidOptions.MaterialId = overrideMaterialId;
                        }
                        extrusionObject = GeometryCreationUtilities.CreateExtrusionGeometry(loops, extrusionDirection, currDepth, solidOptions);
                    }
                    else
                    {
                        foreach (GeometryObject extrusionLayer in extrusionLayers)
                        {
                            extrusions.Add(extrusionLayer);
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (shapeEditScope.MustCreateSolid())
                    {
                        throw ex;
                    }

                    Importer.TheLog.LogError(Id, "Extrusion has an invalid definition for a solid; reverting to mesh.", false);

                    MeshFromGeometryOperationResult meshResult = TessellatedShapeBuilder.CreateMeshByExtrusion(
                        loops, extrusionDirection, currDepth, GetMaterialElementId(shapeEditScope));

                    // will throw if mesh is not available
                    extrusionObject = meshResult.GetMesh();
                }

                if (extrusionObject != null)
                {
                    extrusions.Add(extrusionObject);
                }
            }

            return(extrusions);
        }
Beispiel #32
0
        public static void Execute(
            ExternalCommandData commandData)
        {
            UIApplication uiapp   = commandData.Application;
            UIDocument    uidoc   = uiapp.ActiveUIDocument;
            Document      doc     = uidoc.Document;
            Selection     choices = uidoc.Selection;

            try
            {
                Reference reference = choices.PickObject(
                    ObjectType.Face);

                Element el = doc.GetElement(
                    reference.ElementId);

                Face face = el.GetGeometryObjectFromReference(
                    reference) as Face;

                Mesh mesh = face.Triangulate();

                var familyInstance = el as FamilyInstance;

                if (null != familyInstance)
                {
                    var t = familyInstance
                            .GetTotalTransform();

                    mesh = mesh.get_Transformed(t);
                }

                using (Transaction trans = new Transaction(doc))
                {
                    trans.Start("Create DirectShape from Face");

                    TessellatedShapeBuilder builder
                        = new TessellatedShapeBuilder();

                    builder.OpenConnectedFaceSet(false);

                    List <XYZ> args = new List <XYZ>(3);

                    XYZ[] triangleCorners = new XYZ[3];

                    for (int i = 0; i < mesh.NumTriangles; ++i)
                    {
                        MeshTriangle triangle = mesh.get_Triangle(i);

                        triangleCorners[0] = triangle.get_Vertex(0);
                        triangleCorners[1] = triangle.get_Vertex(1);
                        triangleCorners[2] = triangle.get_Vertex(2);

                        TessellatedFace tesseFace
                            = new TessellatedFace(triangleCorners,
                                                  ElementId.InvalidElementId);

                        if (builder.DoesFaceHaveEnoughLoopsAndVertices(
                                tesseFace))
                        {
                            builder.AddFace(tesseFace);
                        }
                    }

                    builder.CloseConnectedFaceSet();

                    //TessellatedShapeBuilderResult result
                    //  = builder.Build(
                    //    TessellatedShapeBuilderTarget.AnyGeometry,
                    //    TessellatedShapeBuilderFallback.Mesh,
                    //    ElementId.InvalidElementId ); // 2016

                    builder.Target   = TessellatedShapeBuilderTarget.AnyGeometry;    // 2018
                    builder.Fallback = TessellatedShapeBuilderFallback.Mesh;         // 2018

                    builder.Build();                                                 // 2018

                    TessellatedShapeBuilderResult result = builder.GetBuildResult(); // 2018

                    ElementId categoryId = new ElementId(
                        BuiltInCategory.OST_GenericModel);

                    //DirectShape ds = DirectShape.CreateElement(
                    //  doc, categoryId,
                    //  Assembly.GetExecutingAssembly().GetType()
                    //    .GUID.ToString(), Guid.NewGuid().ToString() ); // 2016

                    DirectShape ds = DirectShape.CreateElement(
                        doc, categoryId); // 2018

                    ds.ApplicationId = Assembly.GetExecutingAssembly()
                                       .GetType().GUID.ToString();    // 2018

                    ds.ApplicationDataId = Guid.NewGuid().ToString(); // 2018

                    ds.SetShape(result.GetGeometricalObjects());

                    ds.Name = "MyShape";

                    trans.Commit();
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
        }
Beispiel #33
0
        public static void Execute1(
            ExternalCommandData commandData)
        {
            Transaction trans = null;

            UIDocument uidoc = commandData.Application
                               .ActiveUIDocument;

            Document doc = uidoc.Document;

            try
            {
                Selection choices = uidoc.Selection;

                Reference reference = choices.PickObject(
                    ObjectType.Face);

                Element el = doc.GetElement(
                    reference.ElementId);

                trans = new Transaction(doc, "Create elements");
                trans.Start();

                TessellatedShapeBuilder builder
                    = new TessellatedShapeBuilder();

                builder.OpenConnectedFaceSet(false);

                Face face = el.GetGeometryObjectFromReference(
                    reference) as Face;

                Mesh       mesh = face.Triangulate();
                List <XYZ> args = new List <XYZ>(3);

                XYZ offset = new XYZ();
                if (el.Location is LocationPoint)
                {
                    LocationPoint locationPoint = el.Location
                                                  as LocationPoint;
                    offset = locationPoint.Point;
                }

                for (int i = 0; i < mesh.NumTriangles; i++)
                {
                    MeshTriangle triangle = mesh.get_Triangle(
                        i);

                    XYZ p1 = triangle.get_Vertex(0);
                    XYZ p2 = triangle.get_Vertex(1);
                    XYZ p3 = triangle.get_Vertex(2);

                    p1 = p1.Add(offset);
                    p2 = p2.Add(offset);
                    p3 = p3.Add(offset);

                    args.Clear();
                    args.Add(p1);
                    args.Add(p2);
                    args.Add(p3);

                    TessellatedFace tesseFace
                        = new TessellatedFace(args,
                                              ElementId.InvalidElementId);

                    if (builder.DoesFaceHaveEnoughLoopsAndVertices(
                            tesseFace))
                    {
                        builder.AddFace(tesseFace);
                    }
                }

                builder.CloseConnectedFaceSet();

                //TessellatedShapeBuilderResult result
                //  = builder.Build(
                //    TessellatedShapeBuilderTarget.AnyGeometry,
                //    TessellatedShapeBuilderFallback.Mesh,
                //    ElementId.InvalidElementId ); // 2016

                builder.Target   = TessellatedShapeBuilderTarget.AnyGeometry;    // 2018
                builder.Fallback = TessellatedShapeBuilderFallback.Mesh;         // 2018

                builder.Build();                                                 // 2018

                TessellatedShapeBuilderResult result = builder.GetBuildResult(); // 2018

                ElementId categoryId = new ElementId(
                    BuiltInCategory.OST_GenericModel);

                //DirectShape ds = DirectShape.CreateElement(
                //  doc, categoryId,
                //  Assembly.GetExecutingAssembly().GetType()
                //  .GUID.ToString(), Guid.NewGuid().ToString() ); // 2016

                DirectShape ds = DirectShape.CreateElement(
                    doc, categoryId); // 2018

                ds.ApplicationId = Assembly.GetExecutingAssembly()
                                   .GetType().GUID.ToString();    // 2018

                ds.ApplicationDataId = Guid.NewGuid().ToString(); // 2018

                ds.SetShape(result.GetGeometricalObjects());

                ds.Name = "MyShape";

                trans.Commit();
            }
            catch (Exception ex)
            {
                if (trans != null)
                {
                    trans.RollBack();
                }

                Debug.Print(ex.Message);
            }
        }
Beispiel #34
0
        // Insipred by
        // https://github.com/DynamoDS/DynamoRevit/blob/master/src/Libraries/RevitNodes/GeometryConversion/ProtoToRevitMesh.cs
        public IList <GeometryObject> MeshToNative(Mesh mesh, TessellatedShapeBuilderTarget target = TessellatedShapeBuilderTarget.Mesh, TessellatedShapeBuilderFallback fallback = TessellatedShapeBuilderFallback.Salvage)
        {
            var tsb = new TessellatedShapeBuilder()
            {
                Fallback = fallback, Target = target, GraphicsStyleId = ElementId.InvalidElementId
            };

            var valid = tsb.AreTargetAndFallbackCompatible(target, fallback);

            tsb.OpenConnectedFaceSet(target == TessellatedShapeBuilderTarget.Solid);

            var vertices = ArrayToPoints(mesh.vertices, mesh.units);

            int i = 0;

            while (i < mesh.faces.Count)
            {
                int n = mesh.faces[i];
                if (n < 3)
                {
                    n += 3; // 0 -> 3, 1 -> 4 to preserve backwards compatibility
                }
                var points = mesh.faces.GetRange(i + 1, n).Select(x => vertices[x]).ToArray();

                if (IsNonPlanarQuad(points))
                {
                    //Non-planar quads will be triangulated as it's more desirable than `TessellatedShapeBuilder.Build`'s attempt to make them planar.
                    //TODO consider triangulating all n > 3 polygons
                    var triPoints = new List <XYZ> {
                        points[0], points[1], points[3]
                    };
                    var face1 = new TessellatedFace(triPoints, ElementId.InvalidElementId);
                    tsb.AddFace(face1);

                    triPoints = new List <XYZ> {
                        points[1], points[2], points[3]
                    };;
                    var face2 = new TessellatedFace(triPoints, ElementId.InvalidElementId);
                    tsb.AddFace(face2);
                }
                else
                {
                    var face = new TessellatedFace(points, ElementId.InvalidElementId);
                    tsb.AddFace(face);
                }

                i += n + 1;
            }

            tsb.CloseConnectedFaceSet();
            try
            {
                tsb.Build();
            }
            catch (Exception e)
            {
                Report.LogConversionError(e);
                return(null);
            }
            var result = tsb.GetBuildResult();

            return(result.GetGeometricalObjects());
        public static void Execute(
            ExternalCommandData commandData)
        {
            Transaction trans = null;

              UIApplication uiapp = commandData.Application;
              UIDocument uidoc = uiapp.ActiveUIDocument;
              Document doc = uidoc.Document;

              try
              {
            Selection choices = uidoc.Selection;

            Reference faceref = choices.PickObject(
              ObjectType.Face );

            string rep = faceref
              .ConvertToStableRepresentation( doc );

            Debug.Assert( rep.EndsWith( ":SURFACE" ),
              "expected stable representation to end with SURFACE" );

            Debug.Print( "Face reference picked: "
              + rep );

            Element el = doc.GetElement(
              faceref.ElementId );

            using( trans = new Transaction( doc ) )
            {
              trans.Start( "Create elements" );

              TessellatedShapeBuilder builder
            = new TessellatedShapeBuilder();

              builder.OpenConnectedFaceSet( false );

              // This may return a face in the family
              // symbol definition with no family instance
              // transform applied. Use the GeometryElement
              // GetTransformed method to retrieve the face
              // with the instance transformation applied.

              Face face = el.GetGeometryObjectFromReference(
            faceref ) as Face;

              Debug.Print( "Face reference property: "
            + ( ( null == face.Reference )
              ? "<nil>"
              : face.Reference.ConvertToStableRepresentation( doc ) ) );

              Transform t = null;

              FamilyInstance fi = el as FamilyInstance;

              if( null != fi )
              {
            // Will this handle a face selected
            // in a nested family instance?
            // Some, yes, but not all.

            //t = fi.GetTransform();

            // This also works for some instances
            // but not all.

            //Transform t1 = fi.GetTotalTransform();

            Options opt = new Options();
            opt.ComputeReferences = true;

            GeometryElement geo = el.get_Geometry( opt );

            GeometryElement geo2 = geo.GetTransformed(
              Transform.Identity );

            Stack<Transform> tstack
              = new Stack<Transform>();

            if( GetTransformStackForObject( tstack,
              geo, doc, rep ) && 0 < tstack.Count )
            {
              Debug.Print( "GetTransformStackForObject "
                + "returned true with tstack count {0}",
                tstack.Count );

              t = Transform.Identity;

              while( 0 < tstack.Count )
              {
                t *= tstack.Pop();
              }
            }
              }

              Mesh mesh = face.Triangulate();

              if( null != t )
              {
            mesh = mesh.get_Transformed( t );
              }

              XYZ[] triangleCorners = new XYZ[3];

              for( int i = 0; i < mesh.NumTriangles; i++ )
              {
            MeshTriangle triangle = mesh.get_Triangle( i );

            triangleCorners[0] = triangle.get_Vertex( 0 );
            triangleCorners[1] = triangle.get_Vertex( 1 );
            triangleCorners[2] = triangle.get_Vertex( 2 );

            XYZ normal = GetNormal( triangleCorners );

            SketchPlane sketchPlane = GetSketchPlane(
              doc, triangleCorners[0], normal );

            DrawModelLineLoop( sketchPlane, triangleCorners );

            TessellatedFace tesseFace
              = new TessellatedFace( triangleCorners,
                ElementId.InvalidElementId );

            if( builder.DoesFaceHaveEnoughLoopsAndVertices(
              tesseFace ) )
            {
              builder.AddFace( tesseFace );
            }
              }

              builder.CloseConnectedFaceSet();

              TessellatedShapeBuilderResult result
            = builder.Build(
              TessellatedShapeBuilderTarget.AnyGeometry,
              TessellatedShapeBuilderFallback.Mesh,
              ElementId.InvalidElementId );

              ElementId categoryId = new ElementId(
            BuiltInCategory.OST_GenericModel );

              DirectShape ds = DirectShape.CreateElement(
            doc, categoryId,
            Assembly.GetExecutingAssembly().GetType().GUID.ToString(),
            Guid.NewGuid().ToString() );

              ds.SetShape( result.GetGeometricalObjects() );

              ds.Name = "MyShape";

              trans.Commit();
            }
              }
              catch( Exception ex )
              {
            TaskDialog.Show( "Error", ex.Message );
              }
        }