十一、元素的创建
-
元素创建的四种方法
类名(className)
元素创建工厂类(ItemFactory)
复制Depulicate
操作工具类Utilities
-
在实践的过程中要创建一个元素,到底用哪一种方法呢?实际上最简单的思路就是到REVITAPI中从第一种方法开始找起,看看有无可用的方法,没有就依次往下去找其他的方法,直到实现你的目标。
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ElementCUD
{
/// <summary>
/// 创建一面墙并且在墙的中部创建一个门
/// </summary>
[Transaction(TransactionMode.Manual)]
public class ElementCreation : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
//获取当前文档
var doc = commandData.Application.ActiveUIDocument.Document;
//要创建一面墙,需要必备几个条件:一条线段、一个标高
//通过一种元素创建方法(类名Line创建),来创建一条直线
var line = Line.CreateBound(new XYZ(0, 0, 0),new XYZ(10, 0, 0));
//创建一个过滤器,过滤并获取出名字为标高1的元素(这里采用linq写法)
var levellist = from element in new FilteredElementCollector(doc).OfClass(typeof(Level)) where element.Name == "标高 1" select element;
//获得结果对象(对找到的集合,取第一个元素,转换成我们需要的Level)
var level = levellist.FirstOrDefault() as Level;
//要创建一个门,其实就是创建一个FamilyInstance,这个的创建方法可以查阅API文档。Document-Create-查阅menbers
//找到public FamilyInstance NewFamilyInstance(XYZ location,FamilySymbol symbol,Element host,StructuralType structuralType)
//即使用位置、类型/符号和主体元素将族的新实例插入到文档中。
//创建好在墙中待放置的门的位置坐标(用线的line.Evaluat()方法,设置中点)
var doorLocation = line.Evaluate(0.5, true);
//找到门的族模型FamilySymbol(假设找到的是ID为94654这个门,在实际项目中一定要用过滤的方法获取)
var doorId = new ElementId(94654);
//获取它的族模型
var doorSymbol = doc.GetElement(doorId) as FamilySymbol;
try
{
//创建一个事务
var transaction = new Transaction(doc,"创建墙体");
//启动事务
transaction.Start();
//创建墙(在revitlookup中查找Wall的Create方法,选择其中的Create Method (Document, Curve, ElementId, Boolean)方法)
//使用默认墙样式在项目内创建新的矩形轮廓墙
var wall = Wall.Create(doc, line, level.Id, false);
//在这面墙的中心创建一个门
doc.Create.NewFamilyInstance(doorLocation, doorSymbol, wall,Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
//提交事务
transaction.Commit();
}
catch(Exception e) //异常处理
{
TaskDialog.Show("zzw", e.Message); //弹出一个对话框,显示报错信息
return Result.Failed;
}
return Result.Succeeded;
}
}
}
-
按照上述代码在revit中去执行,会报一个错误:FamilySymbol is not active(族模型未激活),在revit中点击了门-这个门模型后,再重新载入外部工具,这时候就会正常创建了。可以采用以下办法解决这个问题,加一个if判断(如果族模型未激活,激活它)。
using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ElementCUD { /// <summary> /// 创建一面墙并且在墙的中部创建一个门 /// </summary> [Transaction(TransactionMode.Manual)] public class ElementCreation : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { //获取当前文档 var doc = commandData.Application.ActiveUIDocument.Document; //要创建一面墙,需要必备几个条件:一条线段、一个标高 //通过一种元素创建方法(类名Line创建),来创建一条直线 var line = Line.CreateBound(new XYZ(0, 0, 0),new XYZ(10, 0, 0)); //创建一个过滤器,过滤并获取出名字为标高1的元素(这里采用linq写法) var levellist = from element in new FilteredElementCollector(doc).OfClass(typeof(Level)) where element.Name == "标高 1" select element; //获得结果对象(对找到的集合,取第一个元素,转换成我们需要的Level) var level = levellist.FirstOrDefault() as Level; //要创建一个门,其实就是创建一个FamilyInstance,这个的创建方法可以查阅API文档。Document-Create-查阅menbers //找到public FamilyInstance NewFamilyInstance(XYZ location,FamilySymbol symbol,Element host,StructuralType structuralType) //即使用位置、类型/符号和主体元素将族的新实例插入到文档中。 //创建好在墙中待放置的门的位置坐标(用线的line.Evaluat()方法,设置中点) var doorLocation = line.Evaluate(0.5, true); //找到门的族模型FamilySymbol(假设找到的是ID为94654这个门,在实际项目中一定要用过滤的方法获取) var doorId = new ElementId(94654); //获取它的族模型 var doorSymbol = doc.GetElement(doorId) as FamilySymbol; //激活族模型(加一个判断,如果族模型未激活,激活它) if (!doorSymbol.IsActive) doorSymbol.Activate(); try { //创建一个事务 var transaction = new Transaction(doc,"创建墙体"); //启动事务 transaction.Start(); //创建墙(在revitlookup中查找Wall的Create方法,选择其中的Create Method (Document, Curve, ElementId, Boolean)方法) //使用默认墙样式在项目内创建新的矩形轮廓墙 var wall = Wall.Create(doc, line, level.Id, false); //在这面墙的中心创建一个门 doc.Create.NewFamilyInstance(doorLocation, doorSymbol, wall,Autodesk.Revit.DB.Structure.StructuralType.NonStructural); //提交事务 transaction.Commit(); } catch(Exception e) //异常处理 { TaskDialog.Show("zzw", e.Message); //弹出一个对话框,显示报错信息 return Result.Failed; } return Result.Succeeded; } } }
-
案例创建多面相同的墙(墙中心创建一个门),围着一个点形成一个圆
using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ElementCUD { /// <summary> /// 创建多面相同的墙(墙中心创建一个门),围着一个点形成一个圆 /// </summary> [Transaction(TransactionMode.Manual)] public class ElementCreationWall : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { //获取当前文档 var doc = commandData.Application.ActiveUIDocument.Document; //创建这个围成一个圆形的墙,主要是要解决多面墙的不同位置的问题。本质上就是墙围绕一个圆心以固定角度不断复制的过程。 //先解决标高问题。用过滤器,用linq语法 var levellist = from element in new FilteredElementCollector(doc).OfClass(typeof(Level)) where element.Name == "标高 1" select element; var level = levellist.FirstOrDefault() as Level; //创建一个门,本质上就是创建一个族实例,而且应用的方法是在一个墙上创建门的族实例,查询API文档可以采用这个方法 //public FamilyInstance NewFamilyInstance(XYZ location,FamilySymbol symbol,Element host,StructuralType structuralType) //获取门的族模型 var doorId = new ElementId(94654); var doorSymbol = doc.GetElement(doorId) as FamilySymbol; //加一个判断族模型是否激活,未激活则激活它 if (!doorSymbol.IsActive) doorSymbol.Activate(); try { //创建事务 var transaction = new Transaction(doc,"创建多面墙并围成一个圆"); //启动事务 transaction.Start(); //定义墙的数量 var count = 30; //定义一个半径r1 var r1 = 10; //定义一个半径r2 var r2 = 25; //定义一个角度(用弧度制表示) var alpha = 2 * Math.PI / count; //用循环来绘制所有的墙 for (int i = 0; i < count; i++) { //定义墙的线 var line = Line.CreateBound(new XYZ(r1 * Math.Cos(alpha * i), r1 * Math.Sin(alpha * i), 0), new XYZ(r2 * Math.Cos(alpha * i), r2 * Math.Sin(alpha * i), 0)); //获取到门的位置信息(用Line里面的.Evaluate方法,求中点) var doorLocation = line.Evaluate(0.5, true); //绘制墙 var wall = Wall.Create(doc, line, level.Id, false); //绘制门 doc.Create.NewFamilyInstance(doorLocation, doorSymbol, wall, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); } //提交事务 transaction.Commit(); } catch(Exception e) { TaskDialog.Show("zzw", e.Message); return Result.Failed; } return Result.Succeeded; } } }
-
创建一根梁,让其位置坐标稍稍变化,产生一条警告信息,然后处理失败的警告
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ElementCUD
{
/// <summary>
/// 创建一根梁,让其弹出警告信息(不精确警告),然后消除这个警告
/// </summary>
[Transaction(TransactionMode.Manual)]
public class ElementCreationBeamCaveat : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
//获取当前文档
var doc = commandData.Application.ActiveUIDocument.Document;
//创建一根梁就相当于创建一个族实例,查阅API文档选用这个方法实现
//public FamilyInstance NewFamilyInstance(Curve curve,FamilySymbol symbol,Level level,StructuralType structuralType)
//使用曲线、类型 / 符号和标高将族的新实例插入到文档中。
//获取梁的位置
var location = Line.CreateBound(new XYZ(0, 0, 0), new XYZ(10, 0, 0.02));
//获取梁的标高枚举值(用过滤器+linq语句实现)
var levellist = from element in new FilteredElementCollector(doc).OfClass(typeof(Level)) where element.Name == "标高 1" select element;
//获取梁的标高
var level = levellist.FirstOrDefault() as Level;
//获取梁的族实例
var beamSymbol = doc.GetElement(new ElementId(265299)) as FamilySymbol;
//激活族实例
if (!beamSymbol.IsActive) beamSymbol.Activate();
try
{
//创建事务
var transaction = new Transaction(doc,"创建一根梁");
//消除警告
var options = transaction.GetFailureHandlingOptions();
var processor = new InaccurateFailureProcessor();
options.SetFailuresPreprocessor(processor);
transaction.SetFailureHandlingOptions(options);
//启动事务
transaction.Start();
//绘制梁
doc.Create.NewFamilyInstance(location, beamSymbol,level, Autodesk.Revit.DB.Structure.StructuralType.Beam);
//提交事务
transaction.Commit();
}
catch(Exception e)
{
TaskDialog.Show("zzw", e.Message);
return Result.Failed;
}
return Result.Succeeded;
}
}
public class InaccurateFailureProcessor : IFailuresPreprocessor
{
public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
{
//找到所有失败的消息
var failurelist = failuresAccessor.GetFailureMessages();
//遍历failurelist
foreach (var item in failurelist)
{
//获取每一个failureId
var failureId = item.GetFailureDefinitionId();
//判断,如果failureId等于revit自定义的梁或者支撑的不精确警告
if (failureId == BuiltInFailures.InaccurateFailures.InaccurateBeamOrBrace)
failuresAccessor.DeleteWarning(item);
}
return FailureProcessingResult.Continue;
}
}
}