2023-04-24 16:20:24 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Autodesk.Revit.DB;
|
2023-04-25 15:48:55 +08:00
|
|
|
|
using IDTF.Net;
|
|
|
|
|
using Group = IDTF.Net.Group;
|
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
namespace PDF3D.Addin
|
|
|
|
|
{
|
|
|
|
|
internal class IDTFBuilder
|
|
|
|
|
{
|
|
|
|
|
private readonly Document document;
|
|
|
|
|
private IDTFScene _scene;
|
|
|
|
|
private Dictionary<string, int> _shaderIndex = new Dictionary<string, int>();
|
|
|
|
|
|
2023-04-25 15:48:55 +08:00
|
|
|
|
private Parent nullParent = new Parent() { Name = "<NULL>", Transform = new Transform4x4() };
|
2023-05-11 11:46:35 +08:00
|
|
|
|
private ViewResource ViewResource = new ViewResource() { Name = "ALL" };
|
2023-04-24 16:20:24 +08:00
|
|
|
|
public IDTFBuilder(Autodesk.Revit.DB.Document document)
|
|
|
|
|
{
|
|
|
|
|
this.document = document;
|
|
|
|
|
this._scene = new IDTFScene();
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
|
|
|
|
private void AddDefaultMaterial()
|
2023-04-24 16:20:24 +08:00
|
|
|
|
{
|
2023-04-25 15:48:55 +08:00
|
|
|
|
var mat = new MaterialResource()
|
2023-04-24 16:20:24 +08:00
|
|
|
|
{
|
|
|
|
|
Name = "default",
|
|
|
|
|
MaterialDiffuse = System.Drawing.Color.FromArgb(255, 125, 125, 125),
|
|
|
|
|
};
|
|
|
|
|
this._scene.MaterialResources.Add(mat.Name, mat);
|
2023-05-11 11:46:35 +08:00
|
|
|
|
this._scene.ShaderResources.Add(mat.Name,
|
|
|
|
|
new ShaderResource() { ShaderMaterialName = mat.Name, Name = mat.Name });
|
2023-04-24 16:20:24 +08:00
|
|
|
|
_shaderIndex.Add(mat.Name, this._scene.ShaderResources.Count);
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
private void AddDefaultViewResource()
|
|
|
|
|
{
|
|
|
|
|
if (!this._scene.ViewResources.Any())
|
|
|
|
|
{
|
|
|
|
|
this._scene.ViewResources.Add(ViewResource.Name, ViewResource);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-04-24 16:20:24 +08:00
|
|
|
|
|
|
|
|
|
public bool InsertGroup(string name, string patrent = "")
|
|
|
|
|
{
|
|
|
|
|
if (this._scene.Groups.Any(x => x.Name == name))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-05-11 11:46:35 +08:00
|
|
|
|
var group = new Group()
|
|
|
|
|
{
|
|
|
|
|
Name = name,
|
|
|
|
|
Parents = new List<Parent>()
|
|
|
|
|
{ _scene.Groups.Any(x => x.Name == patrent) ? new Parent(patrent) : nullParent }
|
|
|
|
|
};
|
2023-04-24 16:20:24 +08:00
|
|
|
|
this._scene.Groups.Add(group);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
public bool InsertMaterial(Material material)
|
|
|
|
|
{
|
|
|
|
|
if (material == null)
|
|
|
|
|
{
|
|
|
|
|
if (!this._scene.MaterialResources.ContainsKey("default"))
|
|
|
|
|
{
|
2023-05-11 11:46:35 +08:00
|
|
|
|
AddDefaultMaterial();
|
2023-04-24 16:20:24 +08:00
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (!this._scene.MaterialResources.ContainsKey(material.Name))
|
|
|
|
|
{
|
2023-04-25 15:48:55 +08:00
|
|
|
|
var mat = new MaterialResource()
|
2023-04-24 16:20:24 +08:00
|
|
|
|
{
|
|
|
|
|
Name = material.Name,
|
2023-05-11 11:46:35 +08:00
|
|
|
|
MaterialDiffuse = System.Drawing.Color.FromArgb(255, material.Color.Red, material.Color.Green,
|
|
|
|
|
material.Color.Blue),
|
2023-04-24 16:20:24 +08:00
|
|
|
|
MaterialOpacity = (100 - material.Transparency) / 100f
|
|
|
|
|
};
|
|
|
|
|
this._scene.MaterialResources.Add(mat.Name, mat);
|
2023-05-11 11:46:35 +08:00
|
|
|
|
this._scene.ShaderResources.Add(mat.Name,
|
|
|
|
|
new ShaderResource() { ShaderMaterialName = mat.Name, Name = mat.Name });
|
2023-04-24 16:20:24 +08:00
|
|
|
|
_shaderIndex.Add(mat.Name, this._scene.ShaderResources.Count);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
public bool InsertElement(Element element)
|
|
|
|
|
{
|
2023-04-25 15:48:55 +08:00
|
|
|
|
Parent parent;
|
2023-04-24 16:20:24 +08:00
|
|
|
|
if (element is FamilyInstance fi)
|
|
|
|
|
{
|
|
|
|
|
this.InsertGroup(fi.Symbol.FamilyName, fi.Category.Name);
|
2023-04-25 15:48:55 +08:00
|
|
|
|
parent = new Parent(fi.Symbol.FamilyName);
|
2023-04-24 16:20:24 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-04-25 15:48:55 +08:00
|
|
|
|
parent = new Parent(element.Category.Name);
|
2023-04-24 16:20:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var option = new Options();
|
|
|
|
|
option.ComputeReferences = true;
|
|
|
|
|
option.DetailLevel = ViewDetailLevel.Fine;
|
|
|
|
|
option.IncludeNonVisibleObjects = false;
|
|
|
|
|
GeometryElement geoElement = element.get_Geometry(option);
|
|
|
|
|
var meshData = ConvertGeometryObject(geoElement);
|
|
|
|
|
if (meshData != null && meshData.ModelPositionList.Any())
|
|
|
|
|
{
|
|
|
|
|
var name = element.Name + " " + element.Id.ToString();
|
2023-04-25 15:48:55 +08:00
|
|
|
|
var model = new Model
|
2023-04-24 16:20:24 +08:00
|
|
|
|
{
|
|
|
|
|
Name = name,
|
2023-04-25 15:48:55 +08:00
|
|
|
|
Parents = new List<Parent>() { parent },
|
2023-04-24 16:20:24 +08:00
|
|
|
|
Visibility = ModelVisibility.BOTH
|
|
|
|
|
};
|
2023-04-25 15:48:55 +08:00
|
|
|
|
var modelRes = new ModelResource(ModelType.MESH) { Name = name };
|
2023-04-24 16:20:24 +08:00
|
|
|
|
modelRes.Mesh = meshData;
|
|
|
|
|
|
|
|
|
|
model.Resource = modelRes;
|
|
|
|
|
_scene.Models.Add(model);
|
|
|
|
|
_scene.ModelResources.Add(name, modelRes);
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-11 11:46:35 +08:00
|
|
|
|
internal void InsertView(View3D item)
|
|
|
|
|
{
|
|
|
|
|
AddDefaultViewResource();
|
|
|
|
|
IDTF.Net.View view = new IDTF.Net.View() { Name = item.Name, Resource = ViewResource };
|
|
|
|
|
view.ViewData.ViewAttributeScreenUnit = ViewAttributeScreenUnit.PERCENT;
|
|
|
|
|
XYZ direction = item.ViewDirection.CrossProduct(item.UpDirection);
|
|
|
|
|
view.Parents = new List<Parent>()
|
|
|
|
|
{
|
|
|
|
|
new Parent()
|
|
|
|
|
{
|
|
|
|
|
Name = "<NULL>",
|
|
|
|
|
Transform = new Transform4x4()
|
|
|
|
|
{
|
|
|
|
|
c0r0 = item.ViewDirection.X, c0r1 = item.ViewDirection.Y, c0r2 = item.ViewDirection.Z, c0r3 = 0,
|
|
|
|
|
c1r0 = item.UpDirection.X, c1r1 = item.UpDirection.Y, c1r2 = item.UpDirection.Z, c1r3 = 0,
|
|
|
|
|
c2r0 = direction.X, c2r1 = direction.Y, c2r2 =direction.Z, c2r3 = 0,
|
|
|
|
|
c3r0 = item.Origin.X * 304.8, c3r1 = item.Origin.Y * 304.8, c3r2 = item.Origin.Z * 304.8, c3r3 = 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this._scene.Views.Add(view);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
private MeshData ConvertGeometryObject(GeometryObject go)
|
|
|
|
|
{
|
|
|
|
|
if (go is GeometryElement ge)
|
|
|
|
|
{
|
|
|
|
|
MeshData meshData = new MeshData();
|
|
|
|
|
foreach (var item in ge)
|
|
|
|
|
{
|
|
|
|
|
var data = ConvertGeometryObject(item);
|
|
|
|
|
if (data != null)
|
|
|
|
|
{
|
|
|
|
|
CombineMeshdata(meshData, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
return meshData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (go is GeometryInstance gi)
|
|
|
|
|
{
|
|
|
|
|
return ConvertGeometryObject(gi.GetInstanceGeometry());
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
if (go is Face face)
|
|
|
|
|
{
|
|
|
|
|
var faceMesh = face.Triangulate(0.4);
|
|
|
|
|
MeshData meshData = new MeshData();
|
2023-05-11 11:46:35 +08:00
|
|
|
|
meshData.ModelPositionList.AddRange(faceMesh.Vertices.Select(p =>
|
|
|
|
|
new Point3((float)p.X * 304.8f, (float)p.Y * 304.8f, (float)p.Z * 304.8f)));
|
2023-04-24 16:20:24 +08:00
|
|
|
|
for (int i = 0; i < faceMesh.NumTriangles; i++)
|
|
|
|
|
{
|
|
|
|
|
var tri = faceMesh.get_Triangle(i);
|
2023-05-11 11:46:35 +08:00
|
|
|
|
meshData.MeshFacePositionList.Add(new Int3((int)tri.get_Index(0), (int)tri.get_Index(1),
|
|
|
|
|
(int)tri.get_Index(2)));
|
2023-04-24 16:20:24 +08:00
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
var material = face?.MaterialElementId.IntegerValue > 0
|
2023-05-11 11:46:35 +08:00
|
|
|
|
? (document.GetElement(face?.MaterialElementId) as Autodesk.Revit.DB.Material)
|
|
|
|
|
: null;
|
2023-04-24 16:20:24 +08:00
|
|
|
|
this.InsertMaterial(material);
|
2023-05-11 11:46:35 +08:00
|
|
|
|
var shaderDesc = material == null
|
|
|
|
|
? new ShadingDescription(_shaderIndex["default"])
|
|
|
|
|
: new ShadingDescription(_shaderIndex[material.Name]);
|
2023-04-24 16:20:24 +08:00
|
|
|
|
|
|
|
|
|
meshData.ShadingDescriptionList.Add(shaderDesc);
|
|
|
|
|
for (int i = 0; i < meshData.MeshFacePositionList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
meshData.MeshFaceShadingList.Add(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return meshData;
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
if (go is Mesh mesh)
|
|
|
|
|
{
|
|
|
|
|
MeshData meshData = new MeshData();
|
2023-05-11 11:46:35 +08:00
|
|
|
|
meshData.ModelPositionList.AddRange(mesh.Vertices.Select(p =>
|
|
|
|
|
new Point3((float)p.X * 304.8f, (float)p.Y * 304.8f, (float)p.Z * 304.8f)));
|
2023-04-24 16:20:24 +08:00
|
|
|
|
for (int i = 0; i < mesh.NumTriangles; i++)
|
|
|
|
|
{
|
|
|
|
|
var tri = mesh.get_Triangle(i);
|
2023-05-11 11:46:35 +08:00
|
|
|
|
meshData.MeshFacePositionList.Add(new Int3((int)tri.get_Index(0), (int)tri.get_Index(1),
|
|
|
|
|
(int)tri.get_Index(2)));
|
2023-04-24 16:20:24 +08:00
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
var material = mesh?.MaterialElementId.IntegerValue > 0
|
2023-05-11 11:46:35 +08:00
|
|
|
|
? (document.GetElement(mesh?.MaterialElementId) as Autodesk.Revit.DB.Material)
|
|
|
|
|
: null;
|
2023-04-24 16:20:24 +08:00
|
|
|
|
this.InsertMaterial(material);
|
|
|
|
|
|
2023-05-11 11:46:35 +08:00
|
|
|
|
var shaderDesc = material == null
|
|
|
|
|
? new ShadingDescription(_shaderIndex["default"])
|
|
|
|
|
: new ShadingDescription(_shaderIndex[material.Name]);
|
2023-04-24 16:20:24 +08:00
|
|
|
|
|
|
|
|
|
meshData.ShadingDescriptionList.Add(shaderDesc);
|
|
|
|
|
for (int i = 0; i < meshData.MeshFacePositionList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
meshData.MeshFaceShadingList.Add(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return meshData;
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
if (go is Solid solid)
|
|
|
|
|
{
|
|
|
|
|
var meshData = new MeshData();
|
|
|
|
|
|
|
|
|
|
if (solid.Volume != 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (Face item in solid.Faces)
|
|
|
|
|
{
|
|
|
|
|
var data = ConvertGeometryObject(item);
|
|
|
|
|
if (data != null)
|
|
|
|
|
{
|
|
|
|
|
CombineMeshdata(meshData, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return meshData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CombineMeshdata(MeshData data1, MeshData data2)
|
|
|
|
|
{
|
|
|
|
|
var oldCount = data1.ModelPositionList.Count;
|
|
|
|
|
data1.ModelPositionList.AddRange(data2.ModelPositionList);
|
2023-05-11 11:46:35 +08:00
|
|
|
|
data1.MeshFacePositionList.AddRange(data2.MeshFacePositionList.Select(x =>
|
|
|
|
|
new Int3(x.IntArray[0] + oldCount, x.IntArray[1] + oldCount, x.IntArray[2] + oldCount)));
|
2023-04-24 16:20:24 +08:00
|
|
|
|
for (int i = 0; i < data2.MeshFaceDiffuseColorList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
int index = data2.MeshFaceDiffuseColorList[i].IntArray.ElementAt(0);
|
|
|
|
|
var color = data2.ModelDiffuseColorList[index];
|
|
|
|
|
int colorIndex = data1.ModelDiffuseColorList.IndexOf(color);
|
|
|
|
|
if (colorIndex != -1)
|
|
|
|
|
{
|
|
|
|
|
data1.MeshFaceDiffuseColorList.Add(new Int3(colorIndex, colorIndex, colorIndex));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
data1.ModelDiffuseColorList.Add(color);
|
2023-05-11 11:46:35 +08:00
|
|
|
|
data1.MeshFaceDiffuseColorList.Add(new Int3(data1.ModelDiffuseColorList.Count - 1,
|
|
|
|
|
data1.ModelDiffuseColorList.Count - 1, data1.ModelDiffuseColorList.Count - 1));
|
2023-04-24 16:20:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-04-24 16:20:24 +08:00
|
|
|
|
for (int i = 0; i < data2.MeshFaceShadingList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var index = data2.MeshFaceShadingList[i];
|
|
|
|
|
var shader = data2.ShadingDescriptionList[index];
|
|
|
|
|
if (data1.ShadingDescriptionList.Any(x => x.ShaderID == shader.ShaderID))
|
|
|
|
|
{
|
2023-05-11 11:46:35 +08:00
|
|
|
|
int shaderIndex =
|
|
|
|
|
data1.ShadingDescriptionList.IndexOf(
|
|
|
|
|
data1.ShadingDescriptionList.FirstOrDefault(x => x.ShaderID == shader.ShaderID));
|
2023-04-24 16:20:24 +08:00
|
|
|
|
data1.MeshFaceShadingList.Add(shaderIndex);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
data1.ShadingDescriptionList.Add(shader);
|
|
|
|
|
data1.MeshFaceShadingList.Add(data1.ShadingDescriptionList.Count - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Export(string path)
|
|
|
|
|
{
|
2023-05-06 14:02:12 +08:00
|
|
|
|
Distinct();
|
2023-04-24 16:20:24 +08:00
|
|
|
|
_scene.Export(path);
|
|
|
|
|
}
|
2023-05-05 17:08:24 +08:00
|
|
|
|
|
|
|
|
|
private void Distinct()
|
|
|
|
|
{
|
2023-05-06 14:02:12 +08:00
|
|
|
|
var comparer = new Point3Comparer();
|
2023-05-05 17:08:24 +08:00
|
|
|
|
foreach (var item in _scene.ModelResources.Values)
|
|
|
|
|
{
|
2023-05-06 14:02:12 +08:00
|
|
|
|
var points = item.Mesh.ModelPositionList.Distinct(comparer).ToList();
|
2023-05-05 17:08:24 +08:00
|
|
|
|
if (points.Count != item.Mesh.ModelPositionList.Count)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < item.Mesh.MeshFacePositionList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
Int3 face = item.Mesh.MeshFacePositionList[i];
|
2023-05-06 14:02:12 +08:00
|
|
|
|
int a = points.IndexOf(item.Mesh.ModelPositionList[face.IntArray[0]]);
|
|
|
|
|
int b = points.IndexOf(item.Mesh.ModelPositionList[face.IntArray[1]]);
|
|
|
|
|
int c = points.IndexOf(item.Mesh.ModelPositionList[face.IntArray[2]]);
|
2023-05-05 17:08:24 +08:00
|
|
|
|
item.Mesh.MeshFacePositionList[i] = new Int3(a, b, c);
|
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
|
2023-05-05 17:08:24 +08:00
|
|
|
|
item.Mesh.ModelPositionList = points;
|
|
|
|
|
}
|
2023-05-06 14:02:12 +08:00
|
|
|
|
//List<Point3> points = new List<Point3>();
|
|
|
|
|
//foreach (var point in item.Mesh.ModelPositionList)
|
|
|
|
|
//{
|
|
|
|
|
// var str = point.ToString();
|
|
|
|
|
// if (!points.Any(x => x.ToString() == str))
|
|
|
|
|
// {
|
|
|
|
|
// points.Add(point);
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
//if (points.Count != item.Mesh.ModelPositionList.Count)
|
|
|
|
|
//{
|
|
|
|
|
// var ptStr = points.Select(x => x.ToString()).ToList();
|
|
|
|
|
// for (int i = 0; i < item.Mesh.MeshFacePositionList.Count; i++)
|
|
|
|
|
// {
|
|
|
|
|
// Int3 face = item.Mesh.MeshFacePositionList[i];
|
|
|
|
|
// int a = ptStr.IndexOf(item.Mesh.ModelPositionList[face.IntArray[0]].ToString());
|
|
|
|
|
// int b = ptStr.IndexOf(item.Mesh.ModelPositionList[face.IntArray[1]].ToString());
|
|
|
|
|
// int c = ptStr.IndexOf(item.Mesh.ModelPositionList[face.IntArray[2]].ToString());
|
|
|
|
|
// item.Mesh.MeshFacePositionList[i] = new Int3(a, b, c);
|
|
|
|
|
// }
|
|
|
|
|
// item.Mesh.ModelPositionList = points;
|
|
|
|
|
//}
|
2023-05-05 17:08:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-04-24 16:20:24 +08:00
|
|
|
|
}
|
2023-05-11 11:46:35 +08:00
|
|
|
|
}
|