using System; using System.Linq; using System.Text; using System.Linq.Expressions; using System.Collections; using System.Collections.Generic; using Autodesk.Revit.Attributes; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Creation; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using Document = Autodesk.Revit.DB.Document; using Newtonsoft.Json; using System.IO; using Autodesk.Revit.DB.DirectContext3D; using System.Runtime.CompilerServices; namespace GeoTest { [TransactionAttribute(TransactionMode.Manual)] [RegenerationAttribute(RegenerationOption.Manual)] public class TestCommand : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { var applicationApp = commandData.Application.Application; var app = commandData.Application; var uidoc = app.ActiveUIDocument; var doc = uidoc.Document; var inf=GetData(doc, applicationApp); OutPut(inf); return Result.Succeeded; } private Information GetData(Document doc, Autodesk.Revit.ApplicationServices.Application app) { var instances = new List(); var materials = new List(); var meshes = new List(); int instanceID = 0; var option = GetGeometryOption(app); // Find all Wall instances in the document by using category filter ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_StructuralColumns); // Apply the filter to the elements in the active document, // Use shortcut WhereElementIsNotElementType() to find wall instances only FilteredElementCollector collector = new FilteredElementCollector(doc); IList walls = collector.WherePasses(filter).WhereElementIsNotElementType().ToElements(); foreach (var element in walls) { var materialIds = element.GetMaterialIds(false).ToList(); var thisMaterials = materialIds.Select(x => doc.GetElement(x) as Autodesk.Revit.DB.Material).ToList(); var transformList = new List(); foreach (var mat in thisMaterials) { var color = mat.Color; var newMat = new Material(new List() { color.Red,color.Green,color.Blue}, mat.Transparency); materials.Add(newMat); } if (element is FamilyInstance) { var transform = (element as FamilyInstance).GetTotalTransform(); transformList.Add(transform.BasisX); transformList.Add(transform.BasisY); transformList.Add(transform.BasisZ); } else { var transform = Transform.Identity; transformList.Add(transform.BasisX); transformList.Add(transform.BasisY); transformList.Add(transform.BasisZ); } var geoElement = element.get_Geometry(option); foreach (var geoObject in geoElement) { Solid solid = geoObject as Solid; if (null == solid || 0 == solid.Faces.Size || 0 == solid.Edges.Size) { continue; } var vertices = new List(); var faceVertices = new List();//按顺序将每个面用3个顶点表示 var triInfo = new Dictionary, XYZ>(); var normals = new List(); // Get the faces and edges from solid, and transform the formed points foreach (Face face in solid.Faces) { Autodesk.Revit.DB.Mesh mesh = face.Triangulate(); var count = mesh.NumTriangles; for(int i=0;i(); var triangle = mesh.get_Triangle(i); //normal //(x3 - x1).CrossProduct(x2 - x1) var thisNormal = ((triangle.get_Vertex(2) - triangle.get_Vertex(0)).CrossProduct((triangle.get_Vertex(1) - triangle.get_Vertex(0)))).Normalize(); for (int j=0;j<3;j++) { var vertex = triangle.get_Vertex(j); var sameIndex=vertices.Where(x => x.DistanceTo(vertex) < 0.00001); if (!sameIndex.Any()) { vertices.Add(vertex); vertexIndecies.Add(vertices.Count() - 1); } else { vertexIndecies.Add(vertices.IndexOf(sameIndex.First())); } } triInfo.Add(vertexIndecies, thisNormal); faceVertices.AddRange(vertexIndecies); } } //对每个顶点寻找邻接面 //如果两面夹角小于90度,用几何均值合并normal //如果大于90度,使用各自的normal for (int i = 0; i < vertices.Count; i++) { XYZ vertex = vertices[i]; var adjacentFaces = triInfo.Where(x => x.Key.Contains(i)).ToList(); var jc = adjacentFaces.Count; if (!adjacentFaces.Any()) continue; for (int j = 0; j < jc; j++) { for (int k = j + 1; k < jc; k++) { if (Math.Cos(adjacentFaces[j].Value.AngleTo(adjacentFaces[k].Value)) > 0)//即, XYZ>(adjacentFaces[k].Key, changedNormal); adjacentFaces[k] = tempPair; //回到本层开头重新循环 adjacentFaces.RemoveAt(j); jc--; j--; break; } } } normals.AddRange(adjacentFaces.Select(x => x.Value)); } var newMesh = new Mesh(vertices, faceVertices, normals); meshes.Add(newMesh); var newInstance = new Instance(instanceID, transformList, solid.Visibility, meshes.Count() - 1); instances.Add(newInstance); instanceID++; } } var information = new Information(instances, meshes, materials); return information; } Options GetGeometryOption(Autodesk.Revit.ApplicationServices.Application app) { Autodesk.Revit.DB.Options option = app.Create.NewGeometryOptions(); option.ComputeReferences = true; //打开计算几何引用 option.DetailLevel = ViewDetailLevel.Fine; //视图详细程度为最好 return option; } private void OutPut(Information information) { string fp = System.Windows.Forms.Application.StartupPath + "\\geometryInfo.json"; var path = @"D:\geometryInfo.json"; //FileStream fs1 = new FileStream(fp, FileMode.Create, FileAccess.ReadWrite); var instanceString = JsonConvert.SerializeObject(information); File.WriteAllText(path, instanceString); return; } } public class Information { public List instances { get; set; } public List meshes { get; set; } public List materials { get; set; } public Information(List instances, List meshes, List materials) { this.instances = instances; this.meshes = meshes; this.materials = materials; } } public class Instance { public int id { get; set; } public List> transform { get; set; } public int visible { get; set; } public int meshId { get; set; }//meshID public string info { get; set; } public Instance(int id, List transform, Visibility visible, int meshId) { this.id = id; this.transform = new List>(); foreach(var trans in transform) { var tempTrans = new List() { trans.X, trans.Y, trans.Z }; this.transform.Add(tempTrans); } this.visible = (int)visible; this.meshId = meshId; } } public class Mesh { public List> vertices { get; set; } public List vertexIndices { get; set; } public List> normals { get; set; }//点法向量 public Mesh(List vertices, List vertexIndices, List normals) { this.vertexIndices = vertexIndices; this.vertices = new List>(); foreach(var vertex in vertices) { var tempV = new List() { vertex.X, vertex.Y, vertex.Z }; this.vertices.Add(tempV); } this.normals = new List>(); foreach (var n in normals) { var tempN = new List() { n.X, n.Y, n.Z }; this.normals.Add(tempN); } } } public class Material { public List color { get; set; } public double transparent { get; set; }//透明度 public Material(List color, double transparent) { this.color = color; this.transparent = transparent; } } }