using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.Attributes; using Autodesk.Revit.UI.Selection; using System.IO; using System.Windows.Forms; using Newtonsoft.Json; using System.Collections; namespace WebGL { [Transaction(TransactionMode.Manual)] public class TestCommand : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { #region MyRegion List refes = null; UIDocument uiDoc = commandData.Application.ActiveUIDocument; Document doc = uiDoc.Document; try { refes = uiDoc.Selection.PickObjects(ObjectType.Element, "选择Element").ToList(); } catch { return Result.Cancelled; } List myElements = new List(); List myMaterials = new List(); List myMeshes = new List(); Transaction trans = new Transaction(doc, "1212"); trans.Start(); foreach (var refe in refes) { List points = new List(); Element element = doc.GetElement(refe); Color color = new Color(0, 0, 0); int transparent = 0; var materialIds = element.GetMaterialIds(false).ToList(); foreach (var materialId in materialIds) { var material = doc.GetElement(materialId) as Material; if (material != null) { transparent = material.Transparency; color = material.Color; } myMaterials.Add(new MyMaterial { color = ToHexColor(color), transparent = transparent }); } //顶点索引 List indices = new List(); var solids = GetSolidByElement(element, ViewDetailLevel.Fine); foreach (var solid in solids) { var faces = solid.Faces; //循环每个面 foreach (Face face in faces) { // 对每个面进行三角面片化 Mesh mesh = face.Triangulate(); if (mesh == null) continue; for (int i = 0; i < mesh.NumTriangles; i++) { MeshTriangle triangular = mesh.get_Triangle(i); for (int n = 0; n < 3; n++) { XYZ point = triangular.get_Vertex(n); if (points.Count == 0) { points.Add(point); indices.Add(points.Count - 1); } else { XYZ tempPoint = points.Where(a => a.DistanceTo(point) < 0.01).FirstOrDefault(); if (tempPoint != null) { int index = points.IndexOf(tempPoint); indices.Add(index); } else { points.Add(point); indices.Add(points.Count - 1); } } } } } } //顶点坐标 List listVertices = new List(); foreach (var point in points) { listVertices.Add(point.X * 304.8); listVertices.Add(point.Y * 304.8); listVertices.Add(point.Z * 304.8); } //顶点法线 List normals = new List(); for (int i = 1; i <= indices.Count; i++) { if (i % 3 == 0) { XYZ point1 = points[indices[i - 3]]; XYZ point2 = points[indices[i - 2]]; XYZ point3 = points[indices[i - 1]]; //(P0 - P1) 叉乘 (P2 - P1) var normal_1 = (point2 - point1).CrossProduct(point3 - point1).Normalize(); var normal_2 = (point1 - point2).CrossProduct(point3 - point2).Normalize(); var normal_3 = (point1 - point3).CrossProduct(point1 - point3).Normalize(); double[] normal1 = new double[3]; normal1[0] = normal_1.X; normal1[1] = normal_1.Y; normal1[2] = normal_1.Z; double[] normal2 = new double[3]; normal2[0] = normal_1.X; normal2[1] = normal_1.Y; normal2[2] = normal_1.Z; double[] normal3 = new double[3]; normal3[0] = normal_1.X; normal3[1] = normal_1.Y; normal3[2] = normal_1.Z; //x,y,z normals.Add(normal1[0]); normals.Add(normal1[1]); normals.Add(normal1[2]); normals.Add(normal2[0]); normals.Add(normal2[1]); normals.Add(normal2[2]); normals.Add(normal3[0]); normals.Add(normal3[1]); normals.Add(normal3[2]); } } List transfroms = new List(); transfroms.Add(1); transfroms.Add(0); transfroms.Add(0); transfroms.Add(0); transfroms.Add(0); transfroms.Add(1); transfroms.Add(0); transfroms.Add(0); transfroms.Add(0); transfroms.Add(0); transfroms.Add(1); transfroms.Add(0); transfroms.Add(0); transfroms.Add(0); transfroms.Add(0); transfroms.Add(1); ElementInfo info = new ElementInfo { name = element.Name }; myMeshes.Add(new MyMesh() { indices = indices, vertices = listVertices, material = myMaterials.Count - 1, normals = normals }); myElements.Add(new MyElement() { id = element.Id.ToString(), mesh = myMeshes.Count - 1, transform = transfroms, visible = 1.0f, info = info }); } trans.Commit(); SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "json文件 (*.json)|*.json"; dialog.DefaultExt = ".json"; dialog.Title = "导出配置文件"; if (dialog.ShowDialog() == DialogResult.OK) { var Model = new { instances = myElements, meshes = myMeshes, materials = myMaterials }; File.WriteAllText(dialog.FileName, JsonConvert.SerializeObject(Model, Formatting.Indented)); } #endregion return Result.Succeeded; } private string ToHexColor(Color color) { string R = Convert.ToString(color.Red, 16); if (R == "0") R = "00"; string G = Convert.ToString(color.Green, 16); if (G == "0") G = "00"; string B = Convert.ToString(color.Blue, 16); if (B == "0") B = "00"; string HexColor = "#" + R + G + B; return HexColor; } private IList GetSolidByElement(Element element, ViewDetailLevel viewDetailLevel) { List lstSolid = new List(); try { Options options = new Options(); options.IncludeNonVisibleObjects = false; options.DetailLevel = viewDetailLevel; options.ComputeReferences = true; GeometryElement geoElement = element.get_Geometry(options); IEnumerator enumerator = geoElement.GetEnumerator(); { while (enumerator.MoveNext()) { GeometryObject geoObj = enumerator.Current as GeometryObject; if (geoObj is GeometryInstance) { GeometryInstance geoinstance = geoObj as GeometryInstance; GeometryElement geoObjtmp = geoinstance.GetInstanceGeometry(); //GeometryElement geoObjtmp = geoinstance.GetSymbolGeometry(); IEnumerator enumeratorobj = geoObjtmp.GetEnumerator(); { while (enumeratorobj.MoveNext()) { GeometryObject obj2 = enumeratorobj.Current as GeometryObject; if (obj2 is Solid) { lstSolid.Add(obj2 as Solid); } } } } else if (geoObj is Solid) { lstSolid.Add(geoObj as Solid); } } } } catch { //throw; } return lstSolid; } } public class MyElement { public string id { get; set; } public List transform { get; set; } public float visible { get; set; } public int mesh { get; set; } public ElementInfo info { get; set; } } public class ElementInfo { public string name { get; set; } } public class MyMesh { public List vertices { get; set; } public List normals { get; set; } public List indices { get; set; } public int material { get; set; } } public class MyMaterial { public string color { get; set; } public int transparent { get; set; } } }