using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using RevitAddins;
using System;
using System.Collections.Generic;
using System.Linq;
namespace RevitAddins;
public static class Extensions
{
///
/// 文档的收集器
///
///
public static FilteredElementCollector OfCollector(this Document document) => document == null ? throw new ArgumentNullException(nameof(document), "文档为空") : new(document);
public static object GetValue(this Parameter parameter)
{
object result = null;
switch (parameter.StorageType)
{
case StorageType.None:
break;
case StorageType.Integer:
result = parameter.AsInteger();
break;
case StorageType.Double:
result = parameter.AsDouble();
break;
case StorageType.String:
//Revit数据库存储的值
var str = parameter.AsString();
if (string.IsNullOrEmpty(str))
{
//用户可见的前端显示,如根据单位设置而显示的值
result = parameter.AsValueString();
}
else
{
result = str;
}
break;
case StorageType.ElementId:
result = parameter.AsElementId();
break;
}
return result;
}
///
/// 类型的元素集合
///
///
///
///
public static FilteredElementCollector QueryElementsByType(this Document doc)
where T : Element
{
return doc.OfCollector().OfClass(typeof(T));
}
///
/// 收集特定类别
///
///
///
///
public static FilteredElementCollector QueryElementsByCategory(this Document doc, BuiltInCategory builtInCategory)
{
return doc.OfCollector().OfCategory(builtInCategory);
}
///
/// 收集特定类型
///
///
///
///
///
public static FilteredElementCollector QueryElementsByTypeAndCategory(this Document doc, BuiltInCategory builtInCategory)
where T : Element
{
return doc.OfCollector().OfClass(typeof(T)).OfCategory(builtInCategory);
}
public static FilteredElementCollector OfCollector(this View view)
{
//if (view == null)
//{
// throw new ArgumentNullException(nameof(view));
//}
//if (!view.IsTemplate)
//{
// return new FilteredElementCollector(view.doc, view.Id);
//}
return FilteredElementCollector.IsViewValidForElementIteration(view.Document, view.Id)
? new FilteredElementCollector(view.Document, view.Id)
: throw new ArgumentException("当前视图不可应用收集器");
}
///
/// 收集当前平面视图的某类图元
///
///
///
///
public static FilteredElementCollector QueryInstancesByType(this View view)
where T : Element
{
return view.OfCollector().OfClass(typeof(T)).WhereElementIsNotElementType();
}
///
/// 收集当前平面视图的某类别图元
///
///
///
///
public static FilteredElementCollector QueryElementsByCategoryInView(this View view, BuiltInCategory builtInCategory)
{
return view.OfCollector().OfCategory(builtInCategory).WhereElementIsNotElementType();
}
///
/// 收集当前平面视图的某类图元
///
///
///
///
///
public static FilteredElementCollector QueryElementsByTypeAndCategory(this View view, BuiltInCategory builtInCategory)
where T : Element
{
return view.OfCollector().OfClass(typeof(T)).OfCategory(builtInCategory).WhereElementIsNotElementType();
}
///
/// 过滤项目文件独立模型元素,包含依附在主体上的元素,如楼板边缘、屋顶边缘、墙饰条、封檐板,檐沟等等
///
/// 元素集合
public static FilteredElementCollector OfParentModelCollector(this Document doc)
{
var col = doc.OfCollector()
.WhereElementIsNotElementType()
.Where(
e => e is TopographySurface ||
e is DirectShape ||
e.CanHaveTypeAssigned()
&& e.IsValidObject
&& e.HasPhases()
&& e.ArePhasesModifiable()
&& e.get_BoundingBox(null) != null
&& e.Category is { CategoryType: CategoryType.Model }
&& (e is HostObject || e.Category.Parent == null)
&& e is not Panel
&& e is not Mullion
&& e is not RevitLinkInstance
).Select(e => e.Id).ToList();
if (col.Count == 0)
{
return null;
}
return new FilteredElementCollector(doc, col).WhereElementIsNotElementType();
}
///
/// 过滤项目文件的所有模型元素
///
/// 元素集合
public static FilteredElementCollector OfAllModelCollector(this Document doc)
{
if (doc == null)
{
throw new ArgumentNullException(nameof(doc), "文档为空");
}
var col = doc.OfCollector()
.WhereElementIsNotElementType()
.Where(
e => e is TopographySurface ||
e is DirectShape ||
e.CanHaveTypeAssigned() &&
e.IsValidObject &&
e.HasPhases() &&
e.ViewSpecific == false &&
e.Category is { CategoryType: CategoryType.Model, AllowsBoundParameters: true } &&
e.get_BoundingBox(null) != null &&
e is not RevitLinkInstance).Select(e => e.Id).ToList();
if (col.Count == 0)
{
return null;
}
return new FilteredElementCollector(doc, col).WhereElementIsNotElementType();
}
/////
///// 获取所有最高层级的模型元素,不包含子模型
/////
/////
/////
//public static IEnumerable OfModelElements(this Document doc)
//{
// return doc.OfCollector()
// .WhereElementIsNotElementType()
// .Where(
// e => e is TopographySurface || (
// e.CanHaveTypeAssigned()
// && e.IsValidObject
// && e.get_BoundingBox(null) != null
// && e.HasPhases()
// && e.ViewSpecific == false
// && e.Category is { Parent: null, CategoryType: CategoryType.Model, AllowsBoundParameters: true }
// && e is not Panel
// && e is not Mullion
// && e is not RevitLinkInstance)
// );
//}
/////
///// 所有元素不包括幕墙嵌板,幕墙竖梃、依附图元等等
/////
/////
/////
//public static FilteredElementCollector OfModelCollector(this Document doc)
//{
// if (doc == null)
// {
// throw new ArgumentNullException(nameof(doc), "文档为空");
// }
// var li = doc.OfCollector().WhereElementIsNotElementType()
// .Where(
// e => e is TopographySurface ||
// (e.CanHaveTypeAssigned() &&
// e.HasPhases() &&
// e.Category is { Parent: null, CategoryType: CategoryType.Model } &&
// e is not Panel &&
// e is not Mullion &&
// e is not RevitLinkInstance)).Select(e => e.Id).ToList();
// return new FilteredElementCollector(doc, li).WhereElementIsNotElementType();
//}
///
/// 获取对应类型的元素收集器
///
///
///
///
public static IEnumerable OfType(this Document doc)
where T : Element => doc.OfCollector().OfClass(typeof(T)).OfType();
public static FilteredElementCollector OfClass(this Document doc)
where T : Element
{
return doc.OfCollector().OfClass(typeof(T));
}
///
/// 射线法查找所有的Element
///
/// Dcument
/// 例如:ElementClassFilter filter = new ElementClassFilter(typeof(CableTray))
/// 目标对象
/// 射源
/// 方向
/// 返回该射线
public static IList XRayFindAll(
this Document doc,
ElementFilter filter,
FindReferenceTarget targetRef,
XYZ center,
XYZ direction
)
{
FilteredElementCollector collector = new(doc);
Func isNotTemplate = v3 => !v3.IsTemplate;
var view3D = collector.OfClass(typeof(View3D)).Cast().First(isNotTemplate);
ReferenceIntersector refIntersector = new(filter, targetRef, view3D);
var refWithContexts = refIntersector.Find(center, direction);
if (null == refWithContexts)
{
return null;
}
IList resultElements = [];
foreach (var rwc in refWithContexts)
{
var reference = rwc.GetReference();
var hitElement = doc.GetElement(reference);
if (hitElement != null)
{
resultElements.Add(hitElement);
}
}
return resultElements;
}
///
/// 获取标高范围框
///
/// 最低标高除了包含以上部分,还包含以下部分,最高标高包含以上部分
///
///
public static Dictionary GetLevelRanges(this Document doc)
{
var levels = doc.OfType().Cast().OrderBy(l => l.Elevation).ToList();
Dictionary levelOutlines = [];
//获取标高范围
for (var i = 0; i < levels.Count; i++)
{
var baseLevel = levels[i];
XYZ min = new(double.MinValue, double.MinValue, baseLevel.Elevation);
XYZ max;
Outline outline;
if (i == 0)
{
min = new XYZ(double.MinValue, double.MinValue, double.MinValue);
var topLevel = levels[i + 1];
max = new XYZ(double.MaxValue, double.MaxValue, topLevel.Elevation);
outline = new Outline(min, max);
}
else if (i < levels.Count - 1)
{
var topLevel = levels[i + 1];
max = new XYZ(double.MaxValue, double.MaxValue, topLevel.Elevation);
outline = new Outline(min, max);
}
else//最后一个标高以上
{
max = new XYZ(double.MaxValue, double.MaxValue, double.MaxValue);
outline = new Outline(min, max);
}
levelOutlines.Add(baseLevel, outline);
}
return levelOutlines;
}
///
/// 射线法查找最近的Element
///
/// Dcument
/// 例如:ElementClassFilter filter = new ElementClassFilter(typeof(CableTray))
/// 目标对象
/// 射源
/// 方向
/// 被击中的Element
/// 返回该射线
public static Line XRayFindNearest(
this Document doc,
ElementFilter filter,
FindReferenceTarget targetRef,
XYZ center,
XYZ direction,
ref Element hitElement
)
{
FilteredElementCollector collector = new(doc);
var view3D = collector.OfClass(typeof(View3D)).Cast().First(v3 => !v3.IsTemplate);
var rwc = new ReferenceIntersector(filter, targetRef, view3D).FindNearest(center, direction);
if (null == rwc)
{
return null;
}
var reference = rwc.GetReference();
var intersection = reference.GlobalPoint;
hitElement = doc.GetElement(reference);
Line result = null;
if (!center.IsAlmostEqualTo(intersection))
{
result = Line.CreateBound(center, intersection);
}
else
{
hitElement = null;
}
return result;
}
public static TResult Invoke(this Document doc, Func func, string name = "default")
{
using var tr = new Transaction(doc, name);
tr.Start();
var result = func(tr);
var status = tr.GetStatus();
switch (status)
{
case TransactionStatus.Started:
tr.Commit();
return result;
case TransactionStatus.Committed:
case TransactionStatus.RolledBack:
return result;
case TransactionStatus.Error:
tr.RollBack();
return result;
default:
return result;
}
}
public static TResult InvokeGroup(this Document doc, Func func, string name = "default")
{
using var tg = new TransactionGroup(doc, name);
tg.Start();
var result = func(tg);
var status = tg.GetStatus();
switch (status)
{
case TransactionStatus.Started:
tg.Assimilate();
//tr.Commit();
return result;
case TransactionStatus.Committed:
case TransactionStatus.RolledBack:
return result;
case TransactionStatus.Error:
tg.RollBack();
return result;
default:
return result;
}
}
public static TResult InvokeSub(this Document doc, Func func)
{
using var st = new SubTransaction(doc);
st.Start();
var result = func(st);
var status = st.GetStatus();
switch (status)
{
case TransactionStatus.Started:
st.Commit();
return result;
case TransactionStatus.Committed:
case TransactionStatus.RolledBack:
return result;
case TransactionStatus.Error:
st.RollBack();
return result;
default:
return result;
}
}
//private static void UsingThisClass(doc doc)
//{
// //无返回值
// doc.Invoke(m => { }, "x");
// //有返回值
// doc.Invoke(m =>
// {
// return Level.Create(doc, 5);
// }, "x");
// doc.InvokeGroup(m => { doc.Invoke(mn => { }, "x"); }, "x");
// doc.InvokeGroup(m => { doc.Invoke(mn => { }, "x"); doc.Invoke(mn => { }, "Y"); return Level.Create(doc, 5); }, "x");
// doc.InvokeSub(m => { });
// doc.InvokeSub(m => { return Level.Create(doc, 5); });
//}
public static void Invoke(this Document doc, Action action, string name = "default")
{
using var tr = new Transaction(doc, name);
tr.Start();
action(tr);
var status = tr.GetStatus();
switch (status)
{
case TransactionStatus.Started:
tr.Commit();
return;
case TransactionStatus.Committed:
case TransactionStatus.RolledBack:
return;
case TransactionStatus.Error:
tr.RollBack();
return;
default:
return;
}
}
public static void InvokeGroup(this Document doc, Action action, string name = "default")
{
using var tg = new TransactionGroup(doc, name);
tg.Start();
action(tg);
var status = tg.GetStatus();
switch (status)
{
case TransactionStatus.Started:
//tr.Commit();
tg.Assimilate();
return;
case TransactionStatus.Committed:
case TransactionStatus.RolledBack:
break;
case TransactionStatus.Error:
tg.RollBack();
return;
default:
return;
}
}
public static void InvokeSub(this Document doc, Action action)
{
using var st = new SubTransaction(doc);
st.Start();
action(st);
var status = st.GetStatus();
switch (status)
{
case TransactionStatus.Started:
st.Commit();
return;
case TransactionStatus.Committed:
case TransactionStatus.RolledBack:
break;
case TransactionStatus.Error:
st.RollBack();
return;
default:
return;
}
}
}