最近做的这个项目,涉及到提取链接CAD中的所有多段线,并根据这些多段线的几何信息做一些分析,但是产生了一些意想不到的问题。
通过网上流传的提取手段,并不能完全提取CAD中的所有多段线。有时候甚至只提取你不想要的多段线。下面的代码片段是博主helloyangkl提供的解决方案,原文链接为:(174条消息) revit二次开发——基于teigha读取CAD几何与文字(提供源码、引用包与异常解决)_helloyangkl的博客-CSDN博客 他的模型类CADGeometryModel应该是忘加了,我给他补充了下。由于我的模型类中的属性名跟他的略有不同,所以朋友们在粘贴复制做测试的时候,需要自己稍微修改下部分内容,注意甄别。
通过这种方法,并不能得到CAD中的所有多段线,正如我前文中描述的。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.Revit; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using CreatBridgeForRevit2018.ElementsSelect; using CreatBridgeForRevit2018.Filter; using Teigha.Runtime; using Teigha.DatabaseServices; using System.IO; using System.Collections; using Teigha.Geometry; namespace CreatBridgeForRevit2018.ReadCAD { class ReadCADUtils { static string dll = @"D:\Desktop\RvtToDwg\bin\Debug\TD_Mgd.dll";//手动指定引用dll路径 Assembly a = Assembly.UnsafeLoadFrom(dll); ///
/// 取得CAD里的线,包括直线、多段线、圆曲线 /// /// ///public List GetCADCurves(string dwgFile) { List listCADModels = new List (); 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 listPoints = new List (); 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; Autodesk.Revit.DB.Line revitLine = Autodesk.Revit.DB.Line.CreateBound(ConverCADPointToRevitPoint(line.StartPoint), ConverCADPointToRevitPoint(line.EndPoint)); 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; } /// /// 毫米转化成英寸 /// /// ///private double MillimetersToUnits(double value) { return UnitUtils.ConvertToInternalUnits(value, DisplayUnitType.DUT_MILLIMETERS); } /// /// 将CAD里的点转化为Revit里的点 /// /// ///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 Angle { get; set; } public string Layer { get; set; } public CADTextModel() { Location = null; Text = ""; Angle = 0; Layer = ""; } } public class CADGeometryModel { public Autodesk.Revit.DB.PolyLine revitPolyLine { get; set; } public Teigha.DatabaseServices.Polyline cadPolyLine { get; set; } public string LayerName { get; set; } public Autodesk.Revit.DB.Curve revitCurve { get; set; } public Teigha.DatabaseServices.Curve cadCurve { get; set; } } }
经过分析我发现,原因在于:在CAD中多段线是由三种类型组成的,即Polyline,Polyline2d,Polyline3d。而上文的代码只能提取Polyline。
我们在识别到Polyline2d,Polyline3d时,可以通过polyline.ConvertFrom(entity,transferId)的方法将Polyline2d,Polyline3d转化为Polyline以后,再做处理。详细代码如下:
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Teigha.DatabaseServices;
using Teigha.Geometry;
using Teigha.Runtime;
namespace FamilyManagerUI.Function
{
class ReadCADUtils
{
static string dll = @"E:\CSharp\BigProject\dll\TD_Mgd.dll";//手动指定引用dll路径
Assembly a = Assembly.UnsafeLoadFrom(dll);
///
/// 取得链接cad的路径
///
///
///
///
public string GetCADPath(ElementId cadLinkTypeID, Document revitDoc)
{
CADLinkType cadLinkType = revitDoc.GetElement(cadLinkTypeID) as CADLinkType;
return ModelPathUtils.ConvertModelPathToUserVisiblePath(cadLinkType.GetExternalFileReference().GetAbsolutePath());
}
///
/// 取得CAD的文字信息
///
///
///
public List GetCADTextInfo(string dwgFile)
{
List listCADModels = new List();
using (var service = new Services())
{
using (var database = new Database(false, true))
{
try
{
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.Angle = 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.Angle = mText.Rotation;
model.Layer = mText.Layer;
listCADModels.Add(model);
break;
}
}
}
}
}
}
}
}
catch (System.Exception)
{
throw;
}
}
}
return listCADModels;
}
///
/// 取得cad的图层名称
///
///
///
public IList GetLayerName(string dwgFile)
{
IList cadLayerNames = new List();
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;
}
///
/// 取得CAD里的线,包括直线、多段线、圆曲线
///
///
///
public List GetCADCurves(string dwgFile, Autodesk.Revit.ApplicationServices.Application application)
{
List listCADModels = new List();
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); // CSDN上用的entity
DBObject obj= trans.GetObject(id, OpenMode.ForWrite); // G站上的大佬用的DBObject
CADGeometryModel geoModel = new CADGeometryModel();
switch (obj.GetType().Name)
{
case "DBPoint":
DBPoint dbpoint = (DBPoint)obj;
break;
case "Line":
Teigha.DatabaseServices.Line line = (Teigha.DatabaseServices.Line)obj;
//if (line.Layer != layerName) break;
if (ConverCADPointToRevitPoint(line.StartPoint).DistanceTo(ConverCADPointToRevitPoint(line.EndPoint)) <= application.ShortCurveTolerance) break;
Autodesk.Revit.DB.Line revitLine = Autodesk.Revit.DB.Line.CreateBound(ConverCADPointToRevitPoint(line.StartPoint), ConverCADPointToRevitPoint(line.EndPoint));
listCADModels.Add(new CADGeometryModel() { revitCurve = revitLine as Autodesk.Revit.DB.Curve, LayerName = line.Layer, cadCurve = line });
break;
case "Ellipse":
Teigha.DatabaseServices.Ellipse ellipse = (Teigha.DatabaseServices.Ellipse)obj;
//if (ellipse.Layer != layerName) break;
break;
case "Arc":
Teigha.DatabaseServices.Arc arc = (Teigha.DatabaseServices.Arc)obj;
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() { revitCurve = revitArc as Autodesk.Revit.DB.Curve, LayerName = arc.Layer, cadCurve = arc });
//if (arc.Layer != layerName) break;
break;
case "Circle":
Circle circle = (Circle)obj;
//if (circle.Layer != layerName) break;
break;
case "Polyline":
Teigha.DatabaseServices.Polyline pl = (Teigha.DatabaseServices.Polyline)obj;
IList listPoints = new List();
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() { revitPolyLine = polyLine, LayerName = pl.Layer, cadPolyLine = pl });
//if (polyline.Layer != layerName) break;
break;
case "Polyline2d":
Teigha.DatabaseServices.Polyline2d pl2d = (Teigha.DatabaseServices.Polyline2d)obj;
Teigha.DatabaseServices.Polyline pl2 = new Teigha.DatabaseServices.Polyline();
pl2.ConvertFrom(pl2d, false);
IList listPoints2 = new List();
for (int i = 0; i < pl2.NumberOfVertices; i++)
{
listPoints2.Add(new XYZ(MillimetersToUnits(pl2.GetPoint2dAt(i).X), MillimetersToUnits(pl2.GetPoint2dAt(i).Y), 0));
}
PolyLine polyLine2 = PolyLine.Create(listPoints2);
listCADModels.Add(new CADGeometryModel() { revitPolyLine = polyLine2, LayerName = pl2.Layer, cadPolyLine = pl2 });
//if (polyline.Layer != layerName) break;
break;
case "DBText":
DBText dBText = (DBText)obj;
//if (dBText.Layer != layerName) break;
break;
case "Region":
Region region = (Region)obj;
//if (region.Layer != layerName) break;
break;
default:
break;
}
}
}
}
}
}
}
}
}
return listCADModels;
}
///
/// 毫米转化成英寸
///
///
///
private double MillimetersToUnits(double value)
{
return UnitUtils.ConvertToInternalUnits(value, DisplayUnitType.DUT_MILLIMETERS);
}
///
/// 将CAD里的点转化为Revit里的点
///
///
///
private XYZ ConverCADPointToRevitPoint(Point3d point)
{
return new XYZ(MillimetersToUnits(point.X), MillimetersToUnits(point.Y), MillimetersToUnits(point.Z));
}
}
public class CADGeometryModel
{
public Autodesk.Revit.DB.PolyLine revitPolyLine { get; set; }
public Teigha.DatabaseServices.Polyline cadPolyLine { get; set; }
public string LayerName { get; set; }
public Autodesk.Revit.DB.Curve revitCurve { get; set; }
public Teigha.DatabaseServices.Curve cadCurve { get; set; }
}
public class CADTextModel
{
public XYZ Location { get; set; }
public string Text { get; set; }
public double Angle { get; set; }
public string Layer { get; set; }
public CADTextModel()
{
Location = null;
Text = "";
Angle = 0;
Layer = "";
}
}
}