代码目录
图元过滤
按楼层选择墙
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.DB;
namespace WorkingDymo
{
/// <summary>
/// 查找指定标高的墙
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class Class1 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uiDoc = commandData.Application.ActiveUIDocument;
Document doc = uiDoc.Document;
//创建标高收集器
FilteredElementCollector levelcollector = new FilteredElementCollector(doc);
//收集标高元素
IList<Element> levelEle = levelcollector.OfClass(typeof(Level)).ToElements().ToList();
Level level = levelEle[0] as Level;
ElementLevelFilter levelFilter = new ElementLevelFilter(level.Id);
//创建收集器收集wall的元素信息
FilteredElementCollector wallEle = new FilteredElementCollector(doc);
List<ElementId> wallele = wallEle.OfCategory(BuiltInCategory.OST_Walls).OfClass(typeof(Wall)).WherePasses(levelFilter).ToElementIds().ToList();
//高亮显示获得的墙元素
uiDoc.Selection.SetElementIds(wallele);
return Result.Succeeded;
}
}
}
按照楼层选择门窗
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 Autodesk.Revit.UI.Selection;
namespace WorkingDymo
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class WinDoorfFilter : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uiDoc = commandData.Application.ActiveUIDocument;
Document doc = uiDoc.Document;
//根据楼层选择门窗;
//做一个标高收集器,收集标高后将某一项作为案例的标高,再做门窗的过滤器收集门窗,并根据标高过滤器筛选特定的标高
//下面开始做标高收集器
FilteredElementCollector levelcollector = new FilteredElementCollector(doc);
Level level = levelcollector.OfClass(typeof(Level)).ToElements().FirstOrDefault(m=>m.Name=="标高一") as Level;
//创建一个标高过滤器
ElementLevelFilter levelFilter = new ElementLevelFilter(level.Id);
//做一个过滤器收集门窗
FilteredElementCollector eleFilter = new FilteredElementCollector(doc);
//做一个门窗过滤器
ElementCategoryFilter windowsFilter = new ElementCategoryFilter(BuiltInCategory.OST_Windows);
ElementCategoryFilter doorFilter = new ElementCategoryFilter(BuiltInCategory.OST_Doors);
LogicalOrFilter logicalOrFilter = new LogicalOrFilter(windowsFilter, doorFilter);
//收集门窗,并用族实例来剔除上面过滤器里面族类型的内容
IList<ElementId>eleids=eleFilter.WherePasses(logicalOrFilter).OfClass(typeof(FamilyInstance)).ToElementIds().ToList();
//点亮所选门窗
uiDoc.Selection.SetElementIds(eleids);
return Result.Succeeded;
}
}
}
选择交互
梁变高
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
namespace WorkingDymo
{
/// <summary>
/// 抬高梁的方法,这里涉及到iselection,过滤器类的内容,还涉及BuiltinParameter内容查找及对应的内容
/// 进行标高计算时数值是进行除以304.8
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class HigherBeam : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uiDoc = commandData.Application.ActiveUIDocument;
Document doc = uiDoc.Document;
//通过过滤器方式获得梁元素
FilteredElementCollector beamCollector = new FilteredElementCollector(doc);
BeamISelection beamISelection = new BeamISelection();
List<Reference> refers = new List<Reference>();
//鼠标选择一个或者多个梁
try
{
refers = uiDoc.Selection.PickObjects(ObjectType.Element,beamISelection,"选择梁").ToList();
}
catch
{
return Result.Succeeded ;
}
//创建并启动事务
Transaction transaction = new Transaction(doc, "偏移梁");
transaction.Start();
//遍历每一个梁
foreach (Reference refer in refers)
{
//获得梁实例
FamilyInstance beam = doc.GetElement(refer) as FamilyInstance;
//案例以变高50mm为例
double h = 50 /304.8;
BuiltInParameter spara = BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION;
BuiltInParameter epara = BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION;
double sh = beam.get_Parameter(spara).AsDouble();
double eh = beam.get_Parameter(epara).AsDouble();
//设置新值
beam.get_Parameter(spara).Set(sh + h);
beam.get_Parameter(epara).Set(eh + h);
}
transaction.Commit();
return Result.Succeeded;
}
}
选择过滤器ISelection
#region 梁过滤器
class BeamISelection : ISelectionFilter
{
public bool AllowElement(Element elem)
{
Categories categories = elem.Document.Settings.Categories;
if (elem is FamilyInstance && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_StructuralFraming).Id)
{
return true;
}
else
{
return false;
}
;//返回true时内容可被鼠标选定
}
public bool AllowReference(Reference reference, XYZ position)
{
return true;//返回true时表示内容可以被边、点、面选中
}
}
#endregion
}
选择框
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI.Selection;
namespace WorkingDymo
{
[Transaction(TransactionMode.Manual)]
class 选择框 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
//框选一个范围
PickedBox pickedBox = uidoc.Selection.PickBox(PickBoxStyle.Crossing);//crossing 为虚线
XYZ pick1 = pickedBox.Min;
XYZ pick2 = pickedBox.Max;
return Result.Succeeded;
}
}
}
兼容先后选择的写法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
namespace WorkingDymo
{
/// <summary>
/// 兼容先后选取的方法
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class 兼容先后选择 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
//获得已有的选择集合id
List<ElementId> eleids = uidoc.Selection.GetElementIds().ToList();
//过滤已有选中集合中不符合条件的对象
for (int i = 0; i < eleids.Count; i++)
{
ElementId elementId = eleids[i];
//仅保留符合条件的id
if (!(doc.GetElement(elementId) is Wall))
{
eleids.Remove(elementId);
}
}
//如果选择内容为空,则在命令过程中让用户选择对象
if (eleids.Count==0)
{
List<Reference> refer = new List<Reference>();
//选择一个墙
WallISelection wallISelection = new WallISelection();
try
{
refer = uidoc.Selection.PickObjects(ObjectType.Element, wallISelection, "选择墙").ToList();
}
catch
{
return Result.Succeeded;
}
foreach (Reference reference in refer)
{
eleids.Add(reference.ElementId);
}
}
TaskDialog.Show("选择结果", "所选墙的ID是" + eleids);
return Result.Succeeded;
}
}
#region 梁过滤器
class WallISelection : ISelectionFilter
{
public bool AllowElement(Element elem)
{
Categories categories = elem.Document.Settings.Categories;
if (elem is FamilyInstance && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_Walls).Id)
{
return true;
}
else
{
return false;
}
;//返回true时内容可被鼠标选定
}
public bool AllowReference(Reference reference, XYZ position)
{
return true;//返回true时表示内容可以被边、点、面选中
}
}
#endregion
}
构件信息
选择楼板面积
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
namespace WorkingDymo
{
/// <summary>
/// 本例子是楼板面积拾取的案例
/// 关于reference与instance之间的转换,以及注意过滤器像墙和地板这种实例的类型过滤不是familyinstance
/// 而是floor或者wall,根据查询确认,而且关于如何通过实例得到面积的参数,直接get_parameter查找就行了
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class 楼板面积获取 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidco = commandData.Application.ActiveUIDocument;
Document doc = uidco.Document;
//选取文档中的楼板
FloorFilter floorFilter = new FloorFilter();
List<Reference> refers = uidco.Selection.PickObjects(ObjectType.Element, floorFilter, "请选择一个地板").ToList();
double area = 0;
foreach (Reference reference in refers)
{
Floor floor = doc.GetElement(reference) as Floor;
area += floor.get_Parameter(BuiltInParameter.HOST_AREA_COMPUTED).AsDouble();
}
//进行简要的单位转换
double areas = area * 0.3048 * 0.3048;
//获得面积
TaskDialog.Show("获得面积", "获得地板总面积是:" + areas);
return Result.Succeeded;
}
}
#region 楼板过滤器
class FloorFilter : ISelectionFilter
{
public bool AllowElement(Element elem)
{
Categories categories = elem.Document.Settings.Categories;
if (elem is Floor && elem.Category.Id == categories.get_Item(BuiltInCategory.OST_Floors).Id)
{
return true;
}
else
{
return false;
}
;//返回true时内容可被鼠标选定
}
public bool AllowReference(Reference reference, XYZ position)
{
return true;//返回true时表示内容可以被边、点、面选中
}
}
#endregion
}
提取Element的所有solid
#region GetSolidsOfElement:从element里面获取实体的方法
public List<Solid>GetSolidsOfElement(Element ele)
{
//生成事件,指定返回数据的特征
Options options = new Options();
options.DetailLevel = ViewDetailLevel.Fine;
options.ComputeReferences = true;
options.IncludeNonVisibleObjects = true;
//取得构件元素
GeometryElement geoElement = ele.get_Geometry(options);
List<GeometryObject> geoObj = new List<GeometryObject>();
//递归获取集合元素的所有geometryobject
GetAllObj(geoElement, ref geoObj);
//转为solid的集合
List<Solid> solids = geoObj.ConvertAll(m => m as Solid);
return solids;
}
#endregion
#region GetAllObj获得geometry的方法
//获得geometryobject的递归算法
public void GetAllObj(GeometryElement gele,ref List<GeometryObject>gobjs)
{
if (gele==null)
{
return;
}
//遍历geometryelement里面的geometryobject
IEnumerator<GeometryObject> enumerator = gele.GetEnumerator();
while(enumerator.MoveNext())
{
GeometryObject geoObject = enumerator.Current;
Type type = geoObject.GetType();
//如果是嵌套的GeometryElement
if (type.Equals(typeof(GeometryElement)))
{
//则递归
GetAllObj(geoObject as GeometryElement, ref gobjs);
}
//如果嵌套的geometryinstance
else if (type.Equals(typeof(GeometryInstance)))
{
//则用getinstancegeometry取得其中的geometryelement再递归
GetAllObj((geoObject as GeometryInstance).GetInstanceGeometry(), ref gobjs);
}
//如果是solid,则存入集合,递归结束
else
{
if(type.Equals(typeof(Solid)))
{
Solid solid = geoObject as Solid;
//去掉可能存在的空Solid
if (solid.Faces.Size>0||solid.Edges.Size>0)
{
gobjs.Add(geoObject);
}
}
}
}
}
#endregion
计算楼梯体积
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
namespace WorkingDymo
{
/// <summary>
/// 计算楼梯体积,本案例包含了element=》solid过程的数据提取
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class 获取楼梯体积 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
//获取楼梯元素
Reference refer = null;
try
{
refer = uidoc.Selection.PickObject(ObjectType.Element, "选择一个楼梯");
}
catch
{
return Result.Succeeded;
}
//获取元素
Element ele = doc.GetElement(refer);
List<Solid> solids = GetSolidsOfElement(ele);
double volume = 0;
foreach (Solid solid in solids)
{
volume += solid.Volume*0.3048*0.3048*0.3048;//获得体积并进行单位转换
}
TaskDialog.Show("楼梯体积", "获取体积是:" + volume);
return Result.Succeeded;
}
#region GetSolidsOfElement:从element里面获取实体的方法
public List<Solid>GetSolidsOfElement(Element ele)
{
//生成事件,指定返回数据的特征
Options options = new Options();
options.DetailLevel = ViewDetailLevel.Fine;
options.ComputeReferences = true;
options.IncludeNonVisibleObjects = true;
//取得构件元素
GeometryElement geoElement = ele.get_Geometry(options);
List<GeometryObject> geoObj = new List<GeometryObject>();
//递归获取集合元素的所有geometryobject
GetAllObj(geoElement, ref geoObj);
//转为solid的集合
List<Solid> solids = geoObj.ConvertAll(m => m as Solid);
return solids;
}
#endregion
#region GetAllObj获得geometry的方法
//获得geometryobject的递归算法
public void GetAllObj(GeometryElement gele,ref List<GeometryObject>gobjs)
{
if (gele==null)
{
return;
}
//遍历geometryelement里面的geometryobject
IEnumerator<GeometryObject> enumerator = gele.GetEnumerator();
while(enumerator.MoveNext())
{
GeometryObject geoObject = enumerator.Current;
Type type = geoObject.GetType();
//如果是嵌套的GeometryElement
if (type.Equals(typeof(GeometryElement)))
{
//则递归
GetAllObj(geoObject as GeometryElement, ref gobjs);
}
//如果嵌套的geometryinstance
else if (type.Equals(typeof(GeometryInstance)))
{
//则用getinstancegeometry取得其中的geometryelement再递归
GetAllObj((geoObject as GeometryInstance).GetInstanceGeometry(), ref gobjs);
}
//如果是solid,则存入集合,递归结束
else
{
if(type.Equals(typeof(Solid)))
{
Solid solid = geoObject as Solid;
//去掉可能存在的空Solid
if (solid.Faces.Size>0||solid.Edges.Size>0)
{
gobjs.Add(geoObject);
}
}
}
}
}
#endregion
}
}
编辑构件
编辑制造商信息
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
namespace WorkingDymo
{
/// <summary>
/// 设置厂家信息,本例题内容较常规,但是要注意制造商相关参数来自symbol里面,需要与表格查询对照起来
/// 内容查询也要由reference到instance这一步,不仅仅在element这一步
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class 编辑构件参数 : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
//获取厂家信息参数
Reference refer = uidoc.Selection.PickObject(ObjectType.Element, "请选择一个设备");
FamilyInstance ele = doc.GetElement(refer) as FamilyInstance;
Parameter parameter = ele.Symbol.get_Parameter(BuiltInParameter.ALL_MODEL_MANUFACTURER);
Transaction transaction = new Transaction(doc, "修改制造商");
transaction.Start();
parameter.Set("优比");
transaction.Commit();
TaskDialog.Show("输出结果", "成功完成制造商名称修改");
return Result.Succeeded;
}
}
}
编辑构件定位
定位线移动
//移动,实例往右上角移动(100,100)
XYZ delta = new XYZ(100 / 304.8, 304.8, 0);
element.Location.Move(delta);
//旋转,示例以远点的Z方向为轴,逆时针旋转45°
Line axis = Line.CreateBound(XYZ.Zero, XYZ.BasisZ);
element.Location.Rotate(axis, 45 * Math.PI / 180);
几何移动
Element element;
//移动,示例往右上角移动
XYZ deltaMove = new XYZ(100 / 304.8, 100 / 304.8, 0);
ElementTransformUtils.MoveElement(doc, element.Id, deltaMove);
//旋转,实例以原点的Z方向为轴,逆时针旋转45°
Line axis = Line.CreateBound(XYZ.Zero, XYZ.BasisZ);
ElementTransformUtils.RotateElement(doc, elemet.id, axis, Math.PI / 4);
//镜像,实例以Y轴为对称轴;
Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisY, XYZ.Zero);
ElementTransformUtils.MirrorElement(doc, element.Id, plane);
//复制,实例网右上角移动(100,100)
XYZ deltaCopy = new XYZ(100 / 304.8, 100 / 304.8, 0);
ElementTransformUtils.CopyElement(doc, element.Id, deltaCopy);
综合案例:柱断墙
求与element相交的结构柱集合
#region ColumnsIntersectElement:与element相交的结构柱集合
/// <summary>
/// 与element相交的结构柱集合
/// </summary>
/// <param name="doc">输入doc文件</param>
/// <param name="e">被相交的元素</param>
/// <returns>返回结构柱</returns>
public IList<ElementId> ColumnsIntersectElement(Document doc,Element e)
{
IList<ElementId> eleids = new List<ElementId>();
//已有连接关系的,用ElementIntersectsElementFilter找不到
ICollection<ElementId> joinedids = JoinGeometryUtils.GetJoinedElements(doc,e);
foreach (ElementId id in joinedids)
{
Element eleTmp = doc.GetElement(id);
//排除相连接元素中非结构柱的元素
if (eleTmp.Category.Id != doc.Settings.Categories.get_Item(BuiltInCategory.OST_StructuralColumns).Id)
continue;
if (!eleids.Contains(id))
{
eleids.Add(id);
}
}
//求element的boundingBox,限制范围以提高效率
BoundingBoxXYZ box = e.get_BoundingBox(doc.ActiveView);
Outline outline = new Outline(box.Min, box.Min);
//建立收集器
FilteredElementCollector collector = new FilteredElementCollector(doc);
//相交过滤
ElementIntersectsElementFilter eleFilter = new ElementIntersectsElementFilter(e);
//BoundingBox相交过滤
BoundingBoxIntersectsFilter bbFilter = new BoundingBoxIntersectsFilter(outline);
collector.WherePasses(eleFilter).WherePasses(bbFilter);
//类别过滤
//由于已通过相交过滤,肯定是实体,因此无需考虑去掉族类型
collector.OfCategory(BuiltInCategory.OST_StructuralColumns);
//加入集合
foreach (ElementId id in collector.ToElementIds())
{
if (!eleids.Contains(id))
{
eleids.Add(id);
}
}
return eleids;
}
#endregion
求面与线的交点
#region IntersectPointOfFaceAndCurve:求面与线的交点
public XYZ IntersectPointOfFaceAndCurve(Face face, Curve curve)
{
//交点数组
IntersectionResultArray result = new IntersectionResultArray();
//枚举,用于判断相交类型
SetComparisonResult setResult = face.Intersect(curve, out result);
XYZ interResult = null;
//Disjoint为不相交
if (SetComparisonResult.Disjoint != setResult)
{
//isEmpty判断是否为空
if (!result.IsEmpty)
interResult = result.get_Item(0).XYZPoint;
}
return interResult;
}
#endregion
获得元素所有的面
#region 获得元素的所有面
public List<Face> GetGeoFaces(Element ele)
{
//存放集合元素的所有面
List<Face> geoFaces = new List<Face>();
//用上一节的方法取得所有几何体solid
List<Solid> solids = GetSolidsOfElement(ele);
//从集合体重提取所有face,存进集合
foreach (Solid solid in solids)
{
foreach (Face face in solid.Faces)
{
if (face.Area > 0)
geoFaces.Add(face);
}
}
return geoFaces;
}
#endregion
#region GetSolidsOfElement:从element里面获取实体的方法
public List<Solid> GetSolidsOfElement(Element ele)
{
//生成事件,指定返回数据的特征
Options options = new Options();
options.DetailLevel = ViewDetailLevel.Fine;
options.ComputeReferences = true;
options.IncludeNonVisibleObjects = true;
//取得构件元素
GeometryElement geoElement = ele.get_Geometry(options);
List<GeometryObject> geoObj = new List<GeometryObject>();
//递归获取集合元素的所有geometryobject
GetAllObj(geoElement, ref geoObj);
//转为solid的集合
List<Solid> solids = geoObj.ConvertAll(m => m as Solid);
return solids;
}
#endregion
#region GetAllObj获得geometry的方法
//获得geometryobject的递归算法
public void GetAllObj(GeometryElement gele, ref List<GeometryObject> gobjs)
{
if (gele == null)
{
return;
}
//遍历geometryelement里面的geometryobject
IEnumerator<GeometryObject> enumerator = gele.GetEnumerator();
while (enumerator.MoveNext())
{
GeometryObject geoObject = enumerator.Current;
Type type = geoObject.GetType();
//如果是嵌套的GeometryElement
if (type.Equals(typeof(GeometryElement)))
{
//则递归
GetAllObj(geoObject as GeometryElement, ref gobjs);
}
//如果嵌套的geometryinstance
else if (type.Equals(typ