Teigha的使用与注意事项
在Revit二次开发中,有时候需要读取链接Cad图纸里面的一些数据,比如文字和各种几何线段,这个时候就需要我们使用Teigha这个第三方库了。
下图是读取cad图纸信息的实际效果:
这里是读取Cad信息的主要代码
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 Teigha.Runtime;
using Teigha.DatabaseServices;
using System.IO;
using System.Collections;
using Teigha.Geometry;
namespace Casting
{
class ReadCADUtils
{
/// <summary>
/// 取得链接cad的路径
/// </summary>
/// <param name="cadLinkTypeID"></param>
/// <param name="revitDoc"></param>
/// <returns></returns>
public string GetCADPath(ElementId cadLinkTypeID, Document revitDoc)
{
CADLinkType cadLinkType = revitDoc.GetElement(cadLinkTypeID) as CADLinkType;
return ModelPathUtils.ConvertModelPathToUserVisiblePath(cadLinkType.GetExternalFileReference().GetAbsolutePath());
}
/// <summary>
/// 取得CAD的文字信息
/// </summary>
/// <param name="dwgFile"></param>
/// <returns></returns>
public List<CADTextModel> GetCADTextInfo(string dwgFile)
{
List<CADTextModel> listCADModels = new List<CADTextModel>();
using (new Services())
{
using (Database database = new Database(false, false))
{
database.ReadDwgFile(dwgFile, FileShare.Read, true, "");
using (var trans = database.TransactionManager.StartTransaction())
{
using (BlockTable table = (BlockTable)database.BlockTableId.GetObject(OpenMode.ForRead))
{
using (SymbolTableEnumerator enumerator = table.GetEnumerator())
{
StringBuilder sb = new StringBuilder();
while (enumerator.MoveNext())
{
using (BlockTableRecord record = (BlockTableRecord)enumerator.Current.GetObject(OpenMode.ForRead))
{
foreach (ObjectId id in record)
{
Entity entity = (Entity)id.GetObject(OpenMode.ForRead, false, false);
CADTextModel model = new CADTextModel();
switch (entity.GetRXClass().Name)
{
case "AcDbText":
Teigha.DatabaseServices.DBText text = (Teigha.DatabaseServices.DBText)entity;
model.Location = ConverCADPointToRevitPoint(text.Position);
model.Text = text.TextString;
model.Angel = text.Rotation;
model.Layer = text.Layer;
listCADModels.Add(model);
break;
case "AcDbMText":
Teigha.DatabaseServices.MText mText = (Teigha.DatabaseServices.MText)entity;
model.Location = ConverCADPointToRevitPoint(mText.Location);
model.Text = mText.Text;
model.Angel = mText.Rotation;
model.Layer = mText.Layer;
listCADModels.Add(model);
break;
}
}
}
}
}
}
}
}
}
return listCADModels;
}
/// <summary>
/// 取得cad的图层名称
/// </summary>
/// <param name="dwgFile"></param>
/// <returns></returns>
public IList<string> GetLayerName(string dwgFile)
{
IList<string> cadLayerNames = new List<string>();
using (new Services())
{
using (Database database = new Database(false, false))
{
database.ReadDwgFile(dwgFile, FileShare.Read, true, "");
using (var trans = database.TransactionManager.StartTransaction())
{
using (LayerTable lt = (LayerTable)trans.GetObject(database.LayerTableId, OpenMode.ForRead))
{
foreach (ObjectId id in lt)
{
LayerTableRecord ltr = (LayerTableRecord)trans.GetObject(id, OpenMode.ForRead);
cadLayerNames.Add(ltr.Name);
}
}
trans.Commit();
}
}
}
return cadLayerNames;
}
/// <summary>
/// 取得CAD里的线,包括直线、多段线、圆曲线
/// </summary>
/// <param name="dwgFile"></param>
/// <returns></returns>
public List<CADGeometryModel> GetCADCurves(string dwgFile)
{
List<CADGeometryModel> listCADModels = new List<CADGeometryModel>();
using (new Services())
{
using (Database database = new Database(false, false))
{
database.ReadDwgFile(dwgFile, FileShare.Read, true, "");
using (var trans = database.TransactionManager.StartTransaction())
{
using (BlockTable table = (BlockTable)database.BlockTableId.GetObject(OpenMode.ForRead))
{
using (SymbolTableEnumerator enumerator = table.GetEnumerator())
{
StringBuilder sb = new StringBuilder();
while (enumerator.MoveNext())
{
using (BlockTableRecord record = (BlockTableRecord)enumerator.Current.GetObject(OpenMode.ForRead))
{
foreach (ObjectId id in record)
{
Entity entity = (Entity)id.GetObject(OpenMode.ForRead, false, false);
CADGeometryModel geoModel = new CADGeometryModel();
switch (entity.GetRXClass().Name)
{
case "AcDbPolyline":
Teigha.DatabaseServices.Polyline pl = (Teigha.DatabaseServices.Polyline)entity;
IList<XYZ> listPoints = new List<XYZ>();
for (int i = 0; i < pl.NumberOfVertices; i++)
{
listPoints.Add(new XYZ(MillimetersToUnits(pl.GetPoint2dAt(i).X), MillimetersToUnits(pl.GetPoint2dAt(i).Y), 0));
}
PolyLine polyLine = PolyLine.Create(listPoints);
listCADModels.Add(new CADGeometryModel() { CadPolyLine = polyLine, LayerName = pl.Layer });
break;
case "AcDbLine":
Teigha.DatabaseServices.Line line = (Teigha.DatabaseServices.Line)entity;
var start = ConverCADPointToRevitPoint(line.StartPoint);
var end = ConverCADPointToRevitPoint(line.EndPoint);
if (start.DistanceTo(end) < 0.0026) continue;
Autodesk.Revit.DB.Line revitLine = Autodesk.Revit.DB.Line.CreateBound(start, end);
listCADModels.Add(new CADGeometryModel() { CadCurve = revitLine as Autodesk.Revit.DB.Curve, LayerName = line.Layer });
break;
case "AcDbArc":
Teigha.DatabaseServices.Arc arc = (Teigha.DatabaseServices.Arc)entity;
double enda, stara;
if (arc.StartAngle > arc.EndAngle)
{
enda = arc.StartAngle;
stara = arc.EndAngle;
}
else
{
enda = arc.EndAngle;
stara = arc.StartAngle;
}
Autodesk.Revit.DB.Arc revitArc = Autodesk.Revit.DB.Arc.Create(Autodesk.Revit.DB.Plane.CreateByNormalAndOrigin(new XYZ(arc.Normal.X, arc.Normal.Y, arc.Normal.Z),
ConverCADPointToRevitPoint(arc.Center)), MillimetersToUnits(arc.Radius), stara, enda);
listCADModels.Add(new CADGeometryModel() { CadCurve = revitArc as Autodesk.Revit.DB.Curve, LayerName = arc.Layer });
break;
default:
break;
}
}
}
}
}
}
}
}
}
return listCADModels;
}
/// <summary>
/// 毫米转化成英寸
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private double MillimetersToUnits(double value)
{
return UnitUtils.ConvertToInternalUnits(value, DisplayUnitType.DUT_MILLIMETERS);
}
/// <summary>
/// 将CAD里的点转化为Revit里的点
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
private XYZ ConverCADPointToRevitPoint(Point3d point)
{
return new XYZ(MillimetersToUnits(point.X), MillimetersToUnits(point.Y), MillimetersToUnits(point.Z));
}
}
public class CADTextModel {
public XYZ Location { get; set; }
public string Text { get; set; }
public double Angel { get; set; }
public string Layer { get; set; }
}
class CADGeometryModel
{
public PolyLine CadPolyLine { get; set; }
public Autodesk.Revit.DB.Curve CadCurve { get; set; }
public string LayerName { get; set; }
}
}
这里是如何调用上述代码的方法:
//1.通过选择获取元素
var doc = m_uidoc.Document;
Reference reference1 = m_uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, "点击图元");
Element item = doc.GetElement(reference1);
ElementId elementId = item.GetTypeId();
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
ReadCADUtils readCADUtils = new ReadCADUtils();
string cadStirng = readCADUtils.GetCADPath(elementId, doc);
//3.获取CAD文字:
List<CADTextModel> cADTextList = readCADUtils.GetCADTextInfo(cadStirng);
加上这个AssemblyResolve事件是为了使用Addinmanager开发时,无法找到TD_Mgd_3.03_9程序集的异常
下面是窗体的相关代码:
前台xaml
<Window x:Class="Casting.ReadCadWnd"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:RevitPlugin"
mc:Ignorable="d" Height="540" Width="817.069">
<Grid>
<DataGrid x:Name="dg1" HorizontalAlignment="Left" Height="388" Margin="38,26,0,0" VerticalAlignment="Top" Width="610" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="文字信息" Binding="{Binding Text}"
/>
<DataGridTextColumn Header="图层" Binding="{Binding Layer}"/>
<DataGridTextColumn Header="位置" Binding="{Binding Location}"/>
<DataGridTextColumn Header="角度" Binding="{Binding Angel}"/>
</DataGrid.Columns>
</DataGrid>
<Button Content="读取信息" HorizontalAlignment="Left" Margin="282,441,0,0" VerticalAlignment="Top" Width="89" Height="28" Click="Button_Click"/>
</Grid>
</Window>
后台cs文件
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using RevitPlugin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
namespace Casting
{
/// <summary>
/// UserControl1.xaml 的交互逻辑
/// </summary>
public partial class ReadCadWnd : Window
{
public ReadCadWnd()
{
InitializeComponent();
cmd1 = new ExternalCmd();
}
public UIDocument m_uidoc;
ExternalCmd cmd1;
private void Button_Click(object sender, RoutedEventArgs e)
{
cmd1.Exec(() =>
{
//1.通过选择获取元素
var doc = m_uidoc.Document;
Reference reference1 = m_uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, "点击图元");
Element item = doc.GetElement(reference1);
ElementId elementId = item.GetTypeId();
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
ReadCADUtils readCADUtils = new ReadCADUtils();
string cadStirng = readCADUtils.GetCADPath(elementId, doc);
//3.获取CAD文字:
List<CADTextModel> cADTextList = readCADUtils.GetCADTextInfo(cadStirng);
dg1.ItemsSource = cADTextList;
var lines = readCADUtils.GetCADCurves(cadStirng);
});
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var adf = args;
return Assembly.LoadFrom(@"C:\Users\Administrator\source\repos\RevitPlugin\RevitPlugin\bin\Debug\TD_Mgd_3.03_9.dll");
}
}
}
最后在继承外部命令类里面调用这个窗体:
class MepCreate : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
//创建应用程序对象
Autodesk.Revit.ApplicationServices.Application app = commandData.Application.Application;
//创建文档对象
Autodesk.Revit.DB.Document doc = commandData.Application.ActiveUIDocument.Document;
//创建应用程序对象
Autodesk.Revit.UI.UIApplication uiapp = commandData.Application;
//创建文档对象
Autodesk.Revit.UI.UIDocument uiDoc = uiapp.ActiveUIDocument;
//2.获取CAD链接文件路径
// string dll = @"C: \Users\Administrator\source\repos\RevitPlugin\RevitPlugin\bin\Debug\TD_Mgd_3.03_9.dll";//引用位置
//byte[] assemblyBuffer = File.ReadAllBytes(dll);
//Assembly a = Assembly.Load(assemblyBuffer);
//Assembly a = Assembly.UnsafeLoadFrom(dll);
ReadCadWnd cadWnd = new ReadCadWnd();
System.Windows.Interop.WindowInteropHelper mainUI = new System.Windows.Interop.WindowInteropHelper(cadWnd);
mainUI.Owner = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
cadWnd.m_uidoc = uiDoc;
cadWnd.Show();
return Result.Succeeded;
}
}
上述代码中的cmd1.Exec()使用了自己封装的Revit外部事件,详细代码如下:
using Autodesk.Revit.UI;
using System;
namespace RevitPlugin
{
internal class ExternalCmd
{
public ExternalCmd()
{
_event = ExternalEvent.Create(EventHandler);
}
private ExternalEvent _event;
ExternalEventHandler EventHandler = new ExternalEventHandler();
public void Exec(Action action)
{
EventHandler.Action = action;
_event.Raise();
}
}
internal class ExternalEventHandler : IExternalEventHandler
{
//private ExternalEventHandler() { }
private static ExternalEventHandler _instance;
public Action Action { get; set; }
public static ExternalEventHandler Instance
{
get
{
if (_instance == null)
_instance = new ExternalEventHandler();
return _instance;
}
}
public void Execute(UIApplication app)
{
try
{
Action.Invoke();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
}
}
public string GetName()
{
return "UserActionCommon";
}
}
}