// 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) { 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()); }
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); }
private void AddFaceToTessellatedShapeBuilder(TessellatedFace theFace, bool extraFace) { TessellatedShapeBuilder.AddFace(theFace); TessellatedFaceBoundary.Clear(); FaceMaterialId = ElementId.InvalidElementId; if (extraFace) { ExtraCreatedFacesCount++; } else { CreatedFacesCount++; } }
/// <summary> /// Stop collecting edges for a face to create a BRep solid. /// </summary> public void StopCollectingFace() { if (m_TessellatedShapeBuilder == null || m_TessellatedFaceBoundary == null) { throw new InvalidOperationException("StartCollectingFace has not been called."); } TessellatedFace theFace = new TessellatedFace(m_TessellatedFaceBoundary, m_faceMaterialId); m_TessellatedShapeBuilder.AddFace(theFace); m_TessellatedFaceBoundary.Clear(); m_faceMaterialId = ElementId.InvalidElementId; }
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()); }
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(); } }
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()); }
/// <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()); }
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()); }
/// <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); }
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 ); // 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) { TaskDialog.Show("Error", ex.Message); } }
/// <summary> /// This is to create a bounding box mesh for geometries which have errors during the tessellating process /// </summary> /// <param name="minPoint"></param> /// <param name="maxPoint"></param> /// <param name="performHostUnitConversion"></param> /// <returns></returns> public static IList <GeometryObject> CreateBoundingBoxMeshForErrors(Autodesk.DesignScript.Geometry.Point minPoint, Autodesk.DesignScript.Geometry.Point maxPoint, bool performHostUnitConversion = true) { double x0 = minPoint.X; double y0 = minPoint.Y; double z0 = minPoint.Z; double x1 = maxPoint.X; double y1 = maxPoint.Y; double z1 = maxPoint.Z; x0 -= 1.0; y0 -= 1.0; z0 -= 1.0; x1 += 1.0; y1 += 1.0; z1 += 1.0; var tsb = new TessellatedShapeBuilder() { Fallback = TessellatedShapeBuilderFallback.Salvage, Target = TessellatedShapeBuilderTarget.Mesh, GraphicsStyleId = ElementId.InvalidElementId }; tsb.OpenConnectedFaceSet(false); var p0 = new XYZ(x0, y0, z0); var p1 = new XYZ(x1, y0, z0); var p2 = new XYZ(x1, y1, z0); var p3 = new XYZ(x0, y1, z0); var p4 = new XYZ(x0, y0, z1); var p5 = new XYZ(x1, y0, z1); var p6 = new XYZ(x1, y1, z1); var p7 = new XYZ(x0, y1, z1); var f1 = new TessellatedFace(new List <XYZ>() { p0, p1, p2 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f1); var f2 = new TessellatedFace(new List <XYZ>() { p2, p3, p0 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f2); var f3 = new TessellatedFace(new List <XYZ>() { p0, p1, p5 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f3); var f4 = new TessellatedFace(new List <XYZ>() { p5, p4, p0 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f4); var f5 = new TessellatedFace(new List <XYZ>() { p1, p2, p6 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f5); var f6 = new TessellatedFace(new List <XYZ>() { p6, p5, p1 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f6); var f7 = new TessellatedFace(new List <XYZ>() { p2, p3, p7 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f7); var f8 = new TessellatedFace(new List <XYZ>() { p7, p6, p2 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f8); var f9 = new TessellatedFace(new List <XYZ>() { p3, p0, p4 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f9); var f10 = new TessellatedFace(new List <XYZ>() { p4, p7, p3 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f10); var f11 = new TessellatedFace(new List <XYZ>() { p4, p5, p6 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f11); var f12 = new TessellatedFace(new List <XYZ>() { p6, p7, p4 }, MaterialsManager.Instance.DynamoErrorMaterialId); tsb.AddFace(f12); tsb.CloseConnectedFaceSet(); tsb.Build(); var result = tsb.GetBuildResult(); return(result.GetGeometricalObjects()); }
// 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) { 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); var check = !tsb.DoesFaceHaveEnoughLoopsAndVertices(face); 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); var check1 = tsb.DoesFaceHaveEnoughLoopsAndVertices(face1); 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); var check2 = tsb.DoesFaceHaveEnoughLoopsAndVertices(face2); tsb.AddFace(face2); i += 5; } } tsb.CloseConnectedFaceSet(); try { tsb.Build(); } catch (Exception e) { ConversionErrors.Add(e); return(null); } var result = tsb.GetBuildResult(); return(result.GetGeometricalObjects()); }
/// <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()); }
// 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(); } }
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); }
/// <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); } }
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> /// 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 // 2015 // = builder.Build( // TessellatedShapeBuilderTarget.AnyGeometry, // TessellatedShapeBuilderFallback.Mesh, // graphicsStyleId ); builder.Target = TessellatedShapeBuilderTarget.AnyGeometry; // 2017 builder.Fallback = TessellatedShapeBuilderFallback.Mesh; // 2017 builder.GraphicsStyleId = graphicsStyleId; // 2017 builder.Build(); // 2017 //TessellatedShapeBuilderResult r // 2015 DirectShape ds = DirectShape.CreateElement( //doc, _categoryId, appGuid, shapeName ); // 2015 doc, _categoryId); // 2017 ds.ApplicationId = appGuid; // 2017 ds.ApplicationDataId = shapeName; // 2017 //ds.SetShape( r.GetGeometricalObjects() ); // 2015 ds.SetShape(builder.GetBuildResult().GetGeometricalObjects()); // 2017 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); }
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 ); } }
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 ); } }
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); } }
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); } }
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(); } }
// 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());
/// <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; }