ComputerGraphics/20210129/hcx/TestCommand.cs
2021-02-20 16:49:47 +08:00

317 lines
11 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<Reference> 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<MyElement> myElements = new List<MyElement>();
List<MyMaterial> myMaterials = new List<MyMaterial>();
List<MyMesh> myMeshes = new List<MyMesh>();
Transaction trans = new Transaction(doc, "1212");
trans.Start();
foreach (var refe in refes)
{
List<XYZ> points = new List<XYZ>();
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<int> indices = new List<int>();
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<double> listVertices = new List<double>();
foreach (var point in points)
{
listVertices.Add(point.X * 304.8);
listVertices.Add(point.Y * 304.8);
listVertices.Add(point.Z * 304.8);
}
//顶点法线
List<double> normals = new List<double>();
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<double> transfroms = new List<double>();
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<Solid> GetSolidByElement(Element element, ViewDetailLevel viewDetailLevel)
{
List<Solid> lstSolid = new List<Solid>();
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<double> 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<double> vertices { get; set; }
public List<double> normals { get; set; }
public List<int> indices { get; set; }
public int material { get; set; }
}
public class MyMaterial
{
public string color { get; set; }
public int transparent { get; set; }
}
}