Revit二开—基于teigha读取CAD几何与文字

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";
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值