使用环境:Revit 2016、Revit2017(其他版本自测)
市面上有很多Revit插件具备翻模的功能,其基本功能就是将CAD中二维符号转换成Revit中的三维构件,为了实现这个功能,基本可以分为以下几步:
1、将CAD的dwg格式的文件导入到Revit中;
2、选择dwg中的某个图层;
3、隐藏图层;
4、读取图层中所有几何信息,生成三维构件。
明确了任务后,就来看看具体的实现。我们知道,将CAD的dwg文件导入到Revit后,将以一个类似“块”的方式在Revit中显示,元素名是ImportInstance,怎么读取其中的几何信息是我们非常关心的。
importinstance中保留了CAD中的图层,可以通过查询的方式来查看某根线的图层名,RevitAPI提供了PickObject(ObjectType)方法选择元素,在这里使用ObjectType.PointOnElement进行选择,得到了reference后就可以做很多事。一个图层对应revit中的一个Category,在“视图”>“可见性/图形”>“导入类别”可以设置图层的显示隐藏,话不多说直接上代码。(感觉打字好累啊,实现思路具体看代码!)
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JohnnyCoder.CAD
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class ReadCadCommand : IExternalCommand
{
Application app;
Document doc;
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
app = commandData.Application.Application;
doc = uidoc.Document;
//Reference refer = uidoc.Selection.PickObject(ObjectType.Element, "Select a CAD Link");
//Element elem = doc.GetElement(refer);
//GeometryElement geoElem = elem.get_Geometry(new Options());
Reference r = uidoc.Selection.PickObject(ObjectType.PointOnElement);
string ss = r.ConvertToStableRepresentation(doc);
Element elem = doc.GetElement(r);
GeometryElement geoElem = elem.get_Geometry(new Options());
GeometryObject geoObj = elem.GetGeometryObjectFromReference(r);
//获取选中的cad图层
Category targetCategory = null;
ElementId graphicsStyleId = null;
if (geoObj.GraphicsStyleId != ElementId.InvalidElementId)
{
graphicsStyleId = geoObj.GraphicsStyleId;
GraphicsStyle gs = doc.GetElement(geoObj.GraphicsStyleId) as GraphicsStyle;
if (gs != null)
{
targetCategory = gs.GraphicsStyleCategory;
var name = gs.GraphicsStyleCategory.Name;
}
}
//隐藏选中的cad图层
Transaction trans = new Transaction(doc, "隐藏图层");
trans.Start();
if (targetCategory != null)
doc.ActiveView.SetVisibility(targetCategory, false);
trans.Commit();
TransactionGroup transGroup = new TransactionGroup(doc, "绘制模型线");
transGroup.Start();
CurveArray curveArray = new CurveArray();
//判断元素类型
foreach (var gObj in geoElem)
{
GeometryInstance geomInstance = gObj as GeometryInstance;
//坐标转换。如果选择的是“自动-中心到中心”,或者移动了importInstance,需要进行坐标转换
Transform transform = geomInstance.Transform;
if (null != geomInstance)
{
foreach (var insObj in geomInstance.SymbolGeometry)
{
if (insObj.GraphicsStyleId.IntegerValue != graphicsStyleId.IntegerValue)
continue;
if (insObj.GetType().ToString() == "Autodesk.Revit.DB.NurbSpline")
{
//未实现
}
if (insObj.GetType().ToString() == "Autodesk.Revit.DB.Line")
{
Line line = insObj as Line;
XYZ normal = XYZ.BasisZ;
XYZ point = line.GetEndPoint(0);
point = transform.OfPoint(point);
curveArray.Append(TransformLine(transform, line));
CreateModelCurveArray(curveArray, normal, point);
}
if (insObj.GetType().ToString() == "Autodesk.Revit.DB.Arc")
{
//未实现
}
if (insObj.GetType().ToString() == "Autodesk.Revit.DB.PolyLine")
{
PolyLine polyLine = insObj as PolyLine;
IList points = polyLine.GetCoordinates();
for (int i = 0; i < points.Count - 1; i++)
{
Line line = Line.CreateBound(points[i], points[i + 1]);
line = TransformLine(transform, line);
curveArray.Append(line);
}
XYZ normal = XYZ.BasisZ;
XYZ point = points.First();
point = transform.OfPoint(point);
CreateModelCurveArray(curveArray, normal, point);
}
}
}
}
transGroup.Assimilate();
return Result.Succeeded;
}
private void CreateModelCurveArray(CurveArray curveArray, XYZ normal, XYZ point)
{
if (curveArray.Size > 0)
{
Transaction transaction2 = new Transaction(doc);
transaction2.Start("绘制模型线");
try
{
SketchPlane modelSketch = SketchPlane.Create(doc, app.Create.NewPlane(normal, point));
ModelCurveArray modelLine = doc.Create.NewModelCurveArray(curveArray, modelSketch);
}
catch
{
}
transaction2.Commit();
curveArray.Clear();
}
}
private Line TransformLine(Transform transform, Line line)
{
XYZ startPoint = transform.OfPoint(line.GetEndPoint(0));
XYZ endPoint = transform.OfPoint(line.GetEndPoint(1));
Line newLine = Line.CreateBound(startPoint, endPoint);
return newLine;
}
}
}