添加项目文件。

This commit is contained in:
GG Z
2026-02-23 16:57:09 +08:00
parent 63b7094528
commit ebf06999d0
109 changed files with 7194 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{22EDDE0F-0E6A-4C47-AEA5-17027830F236}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DotNet.Exchange.Revit</RootNamespace>
<AssemblyName>DotNet.Exchange.Revit</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="RevitAPI">
<HintPath>D:\Program Files\Autodesk\Revit 2016\RevitAPI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RevitAPIUI">
<HintPath>D:\Program Files\Autodesk\Revit 2016\RevitAPIUI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ExportElment.cs" />
<Compile Include="Export\ExportFactory.cs" />
<Compile Include="Export\GeometryObjectNode.cs" />
<Compile Include="Export\IExportElement.cs" />
<Compile Include="Export\PolygonMeshNode.cs" />
<Compile Include="Export\TriangleFaceNode.cs" />
<Compile Include="Test.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,342 @@
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotNet.Exchange.Revit.Export
{
public class ExportFactory
{
#region fields
private uint m_ExportLevel;
private Document m_Document;
private IExportElement m_ExportHandle;
#endregion
#region properties
/// <summary>
/// 导出等级.
/// 1 - 10默认等级为5.
/// </summary>
public uint ExportLevel
{
get
{
return m_ExportLevel;
}
set
{
m_ExportLevel = value;
}
}
#endregion
#region ctors
public ExportFactory(Document doc, IExportElement exportHandle)
{
if (exportHandle == null || doc == null)
throw new NullReferenceException("exportHandle or doc parameter is null reference !!");
m_ExportLevel = 5;
m_Document = doc;
m_ExportHandle = exportHandle;
}
#endregion
#region methods
/// <summary>
/// 导出指定的元素
/// </summary>
/// <param name="elemArray">The elem array.</param>
public void Export(params Element[] elemArray)
{
for (int i = 0; i < elemArray.Length; i++)
{
this.ElementExport(elemArray[i]);
}
}
/// <summary>
/// 导出当前文档的所有元素.
/// </summary>
public void Export()
{
var view3d = new FilteredElementCollector(m_Document)
.OfClass(typeof(View3D)).FirstOrDefault(m => (m as View3D).Origin != null);
if (view3d == null)
throw new NullReferenceException();
var elems = new FilteredElementCollector(m_Document, view3d.Id).WhereElementIsNotElementType();
var eum = elems.GetElementIterator();
while (eum.MoveNext())
{
this.ElementExport(eum.Current);
}
}
/// <summary>
/// 异步导出指定元素.
/// </summary>
public void AsynchExport(params Element[] elemArray)
{
Task.Run(() => this.Export(elemArray));
}
/// <summary>
/// 异步导出当前文档所有元素.
/// </summary>
public void AsynchExport()
{
Task.Run(() => this.Export());
}
#endregion
#region privates
/// <summary>
/// Elements the export.
/// </summary>
private bool ElementExport(Element elem)
{
if (!m_ExportHandle.OnElementStart(elem))
{
return false;
}
var transform = default(Transform);
if (elem is Instance)
{
transform = (elem as Instance).GetTransform();
}
var objects = this.GetGeometryObject(elem);
if (objects.Count == 0)
{
return false;
}
while (objects.Count > 0)
{
var obj = objects.Pop();
var node = new GeometryObjectNode(obj);
if (!m_ExportHandle.OnGeometryObjectStart(node))
{
return false;
}
if (obj.GetType().Equals(typeof(Solid)))
{
var solid = obj as Solid;
var faces = solid.Faces;
var eum = faces.GetEnumerator();
while (eum.MoveNext())
{
var face = (Face)eum.Current;
// not handle....
m_ExportHandle.OnMaterial(face.MaterialElementId);
var polygonMeshNode = this.FaceConvert(face, transform);
m_ExportHandle.OnPolygonMesh(polygonMeshNode);
}
}
m_ExportHandle.OnGeometryObjectEnd(node);
}
m_ExportHandle.OnElementEnd(elem);
return true;
}
/// <summary>
/// Faces the convert.
/// </summary>
private PolygonMeshNode FaceConvert(Face face, Transform transform)
{
var result = new PolygonMeshNode();
var mesh = face.Triangulate(m_ExportLevel * 0.1);
var temps = new Dictionary<int, XYZ>();
// resolve triangle face..
for (int i = 0; i < mesh.NumTriangles; i++)
{
var triangle = mesh.get_Triangle(i);
var pt1 = triangle.get_Vertex(0);
var pt2 = triangle.get_Vertex(1);
var pt3 = triangle.get_Vertex(2);
var pi1 = (int)triangle.get_Index(0);
var pi2 = (int)triangle.get_Index(1);
var pi3 = (int)triangle.get_Index(2);
if (!temps.ContainsKey(pi1))
{
temps.Add(pi1, pt1);
}
if (!temps.ContainsKey(pi2))
{
temps.Add(pi2, pt2);
}
if (!temps.ContainsKey(pi3))
{
temps.Add(pi3, pt3);
}
result.TriangleFaces.Add(new TriangleFaceNode(pi1, pi2, pi3));
}
var eum = temps.OrderBy(m => m.Key).GetEnumerator();
while (eum.MoveNext())
{
result.Points.Add(eum.Current.Value);
}
// resolve point and uv..
foreach (EdgeArray edgeArray in face.EdgeLoops)
{
foreach (Edge item in edgeArray)
{
result.AddUV(item.EvaluateOnFace(0, face));
result.AddUV(item.EvaluateOnFace(1, face));
}
}
// resolve normal..
if (face.GetType().Equals(typeof(PlanarFace)))
{
var planarFace = face as PlanarFace;
result.AddNormal(planarFace.FaceNormal);
}
else
{
foreach (var item in result.TriangleFaces)
{
var normal = this.GetNormal(result.Points[item.V1], result.Points[item.V2], result.Points[item.V3]);
result.AddNormal(normal);
}
}
if (transform != null)
{
for (int i = 0; i < result.Points.Count; i++)
{
result.Points[i] = transform.OfPoint(result.Points[i]);
}
for (int i = 0; i < result.Normals.Count; i++)
{
result.Normals[i] = transform.OfVector(result.Normals[i]);
}
}
return result;
}
public Autodesk.Revit.DB.Plane ToPlane(XYZ point, XYZ other)
{
var v = other - point;
var angle = v.AngleTo(XYZ.BasisX);
var norm = v.CrossProduct(XYZ.BasisX).Normalize();
if (Math.Abs(angle - 0) < 1e-4)
{
angle = v.AngleTo(XYZ.BasisY);
norm = v.CrossProduct(XYZ.BasisY).Normalize();
}
if (Math.Abs(angle - 0) < 1e-4)
{
angle = v.AngleTo(XYZ.BasisZ);
norm = v.CrossProduct(XYZ.BasisZ).Normalize();
}
return new Autodesk.Revit.DB.Plane(norm, point);
}
/// <summary>
/// Gets the normal.
/// </summary>
private XYZ GetNormal(XYZ p1, XYZ p2, XYZ p3)
{
var v1 = p2 - p1;
var v2 = p3 - p1;
return v1.CrossProduct(v2).Normalize();
}
/// <summary>
/// Gets the geometry object.
/// </summary>
private Stack<GeometryObject> GetGeometryObject(Element elem)
{
var geometryElement = default(GeometryElement);
if (elem is FamilyInstance)
{
geometryElement = (elem as FamilyInstance).GetOriginalGeometry(new Options() { DetailLevel = ViewDetailLevel.Fine});
}
else
{
geometryElement = elem.get_Geometry(new Options() { DetailLevel = ViewDetailLevel.Fine, ComputeReferences = true });
}
var objects = new List<GeometryObject>();
this.RecursionObject(geometryElement, ref objects);
return new Stack<GeometryObject>(objects);
}
/// <summary>
/// Recursions the object.
/// </summary>
private void RecursionObject(GeometryElement geometryElement, ref List<GeometryObject> geometryObjects)
{
if (geometryElement == null)
return;
var eum = geometryElement.GetEnumerator();
while (eum.MoveNext())
{
var current = eum.Current;
var type = current.GetType();
if (type.Equals(typeof(GeometryInstance)))
{
this.RecursionObject((current as GeometryInstance).SymbolGeometry, ref geometryObjects);
}
else if (type.Equals(typeof(GeometryElement)))
{
this.RecursionObject(current as GeometryElement, ref geometryObjects);
}
else
{
if (type.Equals(typeof(Solid)))
{
var solid = current as Solid;
if (solid.Edges.Size == 0 || solid.Faces.Size == 0)
{
continue;
}
}
geometryObjects.Add(current);
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,19 @@
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotNet.Exchange.Revit.Export
{
public class GeometryObjectNode
{
public GeometryObject GeometryObject { get; private set; }
public GeometryObjectNode(GeometryObject geometryObject)
{
this.GeometryObject = geometryObject;
}
}
}

View File

@@ -0,0 +1,47 @@
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotNet.Exchange.Revit.Export
{
/// <summary>
/// IExportElement
/// </summary>
public interface IExportElement
{
/// <summary>
/// 元素开始进行导出时执行.
/// 如果返回结果为true则开始进行此元素导出否则放弃此元素导出.
/// </summary>
bool OnElementStart(Element elem);
/// <summary>
/// 当元素内的GeometryObject进行导出时执行.
/// 如果返回结果为true则开始进行此GeometryObject导出否则放弃此元素导出.
/// </summary>
bool OnGeometryObjectStart(GeometryObjectNode geometryObject);
/// <summary>
/// 开始检索多边形的材质.
/// </summary>
void OnMaterial(ElementId materialId);
/// <summary>
/// 开始检索Solid内的多边形拓扑节点.
/// </summary>
void OnPolygonMesh(PolygonMeshNode polygonMesh);
/// <summary>
/// 当元素内的GeometryObject导出结束时执行.
/// </summary>
void OnGeometryObjectEnd(GeometryObjectNode geometryObject);
/// <summary>
/// 当元素导出结束时开始执行.
/// </summary>
void OnElementEnd(Element elem);
}
}

View File

@@ -0,0 +1,52 @@
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotNet.Exchange.Revit.Export
{
public class PolygonMeshNode
{
public PolygonMeshNode()
{
this.Points = new List<XYZ>();
this.TriangleFaces = new List<TriangleFaceNode>();
this.Normals = new List<XYZ>();
this.UVs = new List<UV>();
}
public List<XYZ> Points { get; private set; }
public List<TriangleFaceNode> TriangleFaces { get; private set; }
public List<XYZ> Normals { get; private set; }
public List<UV> UVs { get; private set; }
internal void AddPoint(XYZ point)
{
var flag = this.Points.FirstOrDefault(m => m.IsAlmostEqualTo(point, 1e-6));
if (flag == null)
{
this.Points.Add(point);
}
}
internal void AddUV(UV uv)
{
var flag = this.UVs.FirstOrDefault(m => m.IsAlmostEqualTo(uv, 1e-6));
if (flag == null)
{
this.UVs.Add(uv);
}
}
internal void AddNormal(XYZ normal)
{
var flag = this.Normals.FirstOrDefault(m => m.IsAlmostEqualTo(normal, 1e-6));
if (flag == null)
{
this.Normals.Add(normal);
}
}
}
}

View File

@@ -0,0 +1,23 @@
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotNet.Exchange.Revit.Export
{
public sealed class TriangleFaceNode
{
internal TriangleFaceNode(int v1, int v2, int v3)
{
this.V1 = (int)v1;
this.V2 = (int)v2;
this.V3 = (int)v3;
}
public int V1 { get; private set; }
public int V2 { get; private set; }
public int V3 { get; private set; }
}
}

View File

@@ -0,0 +1,51 @@
using Autodesk.Revit.DB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DotNet.Exchange.Revit.Export
{
/// <summary>
/// 自定义测试导出类.
/// </summary>
/// <seealso cref="DotNet.Exchange.Revit.Export.IExportElement" />
public class ExportElment : IExportElement
{
// 临时测试
public HashSet<PolygonMeshNode> PolygonMeshNodes = new HashSet<PolygonMeshNode>();
bool IExportElement.OnElementStart(Autodesk.Revit.DB.Element elem)
{
return true;
}
bool IExportElement.OnGeometryObjectStart(GeometryObjectNode solid)
{
return true;
}
void IExportElement.OnMaterial(Autodesk.Revit.DB.ElementId materialId)
{
}
void IExportElement.OnPolygonMesh(PolygonMeshNode polygonMesh)
{
PolygonMeshNodes.Add(polygonMesh);
}
void IExportElement.OnGeometryObjectEnd(GeometryObjectNode solid)
{
}
void IExportElement.OnElementEnd(Autodesk.Revit.DB.Element elem)
{
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("DotNet.Exchange.Revit")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DotNet.Exchange.Revit")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ec829d77-42ee-431c-8606-4c23ab9123fd")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Utility;
using System.Diagnostics;
using Autodesk.Revit.ApplicationServices;
using DotNet.Exchange.Revit.Export;
namespace DotNet.Exchange.Revit
{
/// <summary>
/// 自定义导出测试代码。
/// 备注:自定义导出未经过长时间测试,在此开源是提供一个思路和方法,如果有遇到问题,可联系本人进行讨论.
/// </summary>
/// <seealso cref="Autodesk.Revit.UI.IExternalCommand" />
[Transaction(TransactionMode.Manual)]
public class Test : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
var uiDoc = commandData.Application.ActiveUIDocument;
var doc = uiDoc.Document;
var refer = uiDoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
var elem = doc.GetElement(refer);
var export = new ExportElment();
var exportFactory = new ExportFactory(doc, export);
exportFactory.ExportLevel = 3;
exportFactory.Export(elem);
// 绘制测试,因绘制线速度较慢,所以当需要绘制测试时,请测试少量模型
doc.Invoke(m =>
{
foreach (var polygonMesh in export.PolygonMeshNodes)
{
foreach (var triangleFaces in polygonMesh.TriangleFaces)
{
var p1 = polygonMesh.Points[triangleFaces.V1];
var p2 = polygonMesh.Points[triangleFaces.V2];
var p3 = polygonMesh.Points[triangleFaces.V3];
CreateModelLine(doc, p1, p2);
CreateModelLine(doc, p2, p3);
CreateModelLine(doc, p3, p1);
}
}
});
return Result.Succeeded;
}
private void CreateModelLine(Document doc, XYZ p1, XYZ p2)
{
using (var line = Line.CreateBound(p1, p2))
{
using (var skPlane = SketchPlane.Create(doc, this.ToPlane(p1, p2)))
{
if (doc.IsFamilyDocument)
{
doc.FamilyCreate.NewModelCurve(line, skPlane);
}
else
{
doc.Create.NewModelCurve(line, skPlane);
}
}
}
}
private Autodesk.Revit.DB.Plane ToPlane(XYZ point, XYZ other)
{
var v = other - point;
var angle = v.AngleTo(XYZ.BasisX);
var norm = v.CrossProduct(XYZ.BasisX).Normalize();
if (Math.Abs(angle - 0) < 1e-4)
{
angle = v.AngleTo(XYZ.BasisY);
norm = v.CrossProduct(XYZ.BasisY).Normalize();
}
if (Math.Abs(angle - 0) < 1e-4)
{
angle = v.AngleTo(XYZ.BasisZ);
norm = v.CrossProduct(XYZ.BasisZ).Normalize();
}
return new Autodesk.Revit.DB.Plane(norm, point);
}
}
public static class DocumentExtension
{
/// <summary>
/// 使用委托启动事务.事务内自动进行事务启动,提交、回滚等处理。
/// </summary>
/// <param name="doc">The document.</param>
/// <param name="action">The action.</param>
/// <param name="name">The name.</param>
public static void Invoke(this Document doc, Action<Transaction> action, string name = "default")
{
using (var tr = new Transaction(doc, name))
{
tr.Start();
action(tr);
var status = tr.GetStatus();
switch (status)
{
case TransactionStatus.Started:
tr.Commit();
return;
case TransactionStatus.Committed:
case TransactionStatus.RolledBack:
break;
case TransactionStatus.Error:
tr.RollBack();
return;
default:
return;
}
}
}
}
}