功能更新
This commit is contained in:
566
RevitAddins/Extensions.cs
Normal file
566
RevitAddins/Extensions.cs
Normal file
@@ -0,0 +1,566 @@
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 文档的收集器
|
||||
/// </summary>
|
||||
/// <param name="document"></param>
|
||||
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;
|
||||
}
|
||||
/// <summary>
|
||||
/// 类型的元素集合
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="doc"></param>
|
||||
/// <returns></returns>
|
||||
public static FilteredElementCollector QueryElementsByType<T>(this Document doc)
|
||||
where T : Element
|
||||
{
|
||||
return doc.OfCollector().OfClass(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集特定类别
|
||||
/// </summary>
|
||||
/// <param name="doc"></param>
|
||||
/// <param name="builtInCategory"></param>
|
||||
/// <returns></returns>
|
||||
public static FilteredElementCollector QueryElementsByCategory(this Document doc, BuiltInCategory builtInCategory)
|
||||
{
|
||||
return doc.OfCollector().OfCategory(builtInCategory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集特定类型
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="doc"></param>
|
||||
/// <param name="builtInCategory"></param>
|
||||
/// <returns></returns>
|
||||
public static FilteredElementCollector QueryElementsByTypeAndCategory<T>(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("当前视图不可应用收集器");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集当前平面视图的某类图元
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="view"></param>
|
||||
/// <returns></returns>
|
||||
public static FilteredElementCollector QueryInstancesByType<T>(this View view)
|
||||
where T : Element
|
||||
{
|
||||
return view.OfCollector().OfClass(typeof(T)).WhereElementIsNotElementType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集当前平面视图的某类别图元
|
||||
/// </summary>
|
||||
/// <param name="view"></param>
|
||||
/// <param name="builtInCategory"></param>
|
||||
/// <returns></returns>
|
||||
public static FilteredElementCollector QueryElementsByCategoryInView(this View view, BuiltInCategory builtInCategory)
|
||||
{
|
||||
return view.OfCollector().OfCategory(builtInCategory).WhereElementIsNotElementType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集当前平面视图的某类图元
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="view"></param>
|
||||
/// <param name="builtInCategory"></param>
|
||||
/// <returns></returns>
|
||||
public static FilteredElementCollector QueryElementsByTypeAndCategory<T>(this View view, BuiltInCategory builtInCategory)
|
||||
where T : Element
|
||||
{
|
||||
return view.OfCollector().OfClass(typeof(T)).OfCategory(builtInCategory).WhereElementIsNotElementType();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 过滤项目文件独立模型元素,包含依附在主体上的元素,如楼板边缘、屋顶边缘、墙饰条、封檐板,檐沟等等
|
||||
/// </summary>
|
||||
/// <returns>元素集合</returns>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 过滤项目文件的所有模型元素
|
||||
/// </summary>
|
||||
/// <returns>元素集合</returns>
|
||||
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();
|
||||
}
|
||||
///// <summary>
|
||||
///// 获取所有最高层级的模型元素,不包含子模型
|
||||
///// </summary>
|
||||
///// <param name="doc"></param>
|
||||
///// <returns></returns>
|
||||
//public static IEnumerable<Element> 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)
|
||||
// );
|
||||
//}
|
||||
///// <summary>
|
||||
///// 所有元素不包括幕墙嵌板,幕墙竖梃、依附图元等等
|
||||
///// </summary>
|
||||
///// <param name="doc"></param>
|
||||
///// <returns></returns>
|
||||
//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();
|
||||
//}
|
||||
/// <summary>
|
||||
/// 获取对应类型的元素收集器
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="doc"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> OfType<T>(this Document doc)
|
||||
where T : Element => doc.OfCollector().OfClass(typeof(T)).OfType<T>();
|
||||
public static FilteredElementCollector OfClass<T>(this Document doc)
|
||||
where T : Element
|
||||
{
|
||||
return doc.OfCollector().OfClass(typeof(T));
|
||||
}
|
||||
/// <summary>
|
||||
/// 射线法查找所有的Element
|
||||
/// </summary>
|
||||
/// <param name="doc">Dcument</param>
|
||||
/// <param name="filter">例如:ElementClassFilter filter = new ElementClassFilter(typeof(CableTray))</param>
|
||||
/// <param name="targetRef">目标对象</param>
|
||||
/// <param name="center">射源</param>
|
||||
/// <param name="direction">方向</param>
|
||||
/// <returns>返回该射线</returns>
|
||||
public static IList<Element> XRayFindAll(
|
||||
this Document doc,
|
||||
ElementFilter filter,
|
||||
FindReferenceTarget targetRef,
|
||||
XYZ center,
|
||||
XYZ direction
|
||||
)
|
||||
{
|
||||
FilteredElementCollector collector = new(doc);
|
||||
Func<View3D, bool> isNotTemplate = v3 => !v3.IsTemplate;
|
||||
var view3D = collector.OfClass(typeof(View3D)).Cast<View3D>().First(isNotTemplate);
|
||||
ReferenceIntersector refIntersector = new(filter, targetRef, view3D);
|
||||
var refWithContexts = refIntersector.Find(center, direction);
|
||||
if (null == refWithContexts)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IList<Element> resultElements = [];
|
||||
foreach (var rwc in refWithContexts)
|
||||
{
|
||||
var reference = rwc.GetReference();
|
||||
var hitElement = doc.GetElement(reference);
|
||||
if (hitElement != null)
|
||||
{
|
||||
resultElements.Add(hitElement);
|
||||
}
|
||||
}
|
||||
|
||||
return resultElements;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取标高范围框
|
||||
/// </summary>
|
||||
/// <remarks>最低标高除了包含以上部分,还包含以下部分,最高标高包含以上部分</remarks>
|
||||
/// <param name="doc"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<Level, Outline> GetLevelRanges(this Document doc)
|
||||
{
|
||||
var levels = doc.OfType<Level>().Cast<Level>().OrderBy(l => l.Elevation).ToList();
|
||||
Dictionary<Level, Outline> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 射线法查找最近的Element
|
||||
/// </summary>
|
||||
/// <param name="doc">Dcument</param>
|
||||
/// <param name="filter">例如:ElementClassFilter filter = new ElementClassFilter(typeof(CableTray))</param>
|
||||
/// <param name="targetRef">目标对象</param>
|
||||
/// <param name="center">射源</param>
|
||||
/// <param name="direction">方向</param>
|
||||
/// <param name="hitElement">被击中的Element</param>
|
||||
/// <returns>返回该射线</returns>
|
||||
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<View3D>().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<TResult>(this Document doc, Func<Transaction, TResult> 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<TResult>(this Document doc, Func<TransactionGroup, TResult> 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<TResult>(this Document doc, Func<SubTransaction, TResult> 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<Level>(m =>
|
||||
// {
|
||||
// return Level.Create(doc, 5);
|
||||
// }, "x");
|
||||
|
||||
// doc.InvokeGroup(m => { doc.Invoke(mn => { }, "x"); }, "x");
|
||||
// doc.InvokeGroup<Level>(m => { doc.Invoke(mn => { }, "x"); doc.Invoke(mn => { }, "Y"); return Level.Create(doc, 5); }, "x");
|
||||
// doc.InvokeSub(m => { });
|
||||
// doc.InvokeSub<Level>(m => { return Level.Create(doc, 5); });
|
||||
//}
|
||||
|
||||
public static void Invoke(this Document doc, Action<Transaction> 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<TransactionGroup> 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<SubTransaction> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user