Files
2026-02-21 16:31:24 +08:00

386 lines
13 KiB
C#

using System.Windows;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace ShrlAlgoToolkit.RevitCore.Extensions;
/// SectionView:
/// RightDirection = CropBox.Transform.BasisX;
/// ViewDirection = CropBox.Transform.BasisZ;
/// UpDirection = XYZ.BasisZ =CropBox.Transform.BasisY
public static class ViewExtensions
{
/// <summary>
/// 复制视图
/// </summary>
/// <param name="view"></param>
/// <param name="option"></param>
/// <param name="viewName"></param>
/// <returns></returns>
public static View CopyWithOption(this View view, ViewDuplicateOption option, string viewName = default)
{
if (view.CanViewBeDuplicated(option))
{
var eleId = view.Duplicate(option);
var viewCopy = view.Document.GetElement(eleId) as View;
if (viewName != default)
{
try
{
viewCopy.Name = viewName;
}
catch (Autodesk.Revit.Exceptions.ArgumentException) { }
}
return viewCopy;
}
return null;
}
public static BoundingBoxXYZ GetElementsBox(this View view, List<ElementId> elementIds)
{
BoundingBoxXYZ box = new BoundingBoxXYZ();
var doc = view.Document;
doc.Invoke(ts =>
{
var group = doc.Create.NewGroup(elementIds);
box = group.get_BoundingBox(null);
ts.RollBack();
}, "打组");
return box;
}
/// <summary>
/// 获取多个元素的包围框
/// </summary>
/// <param name="view"></param>
/// <param name="elementIds"></param>
/// <param name="extendXyz"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public static BoundingBoxXYZ GetElementsBox(this View view, List<ElementId> elementIds, int extendXyz = 1)
{
if (view == null)
{
throw new ArgumentNullException(nameof(view), "视图为空");
}
var doc = view.Document;
if (elementIds == null || elementIds.Any())
{
return null;
}
var f = doc.GetElement(
elementIds.FirstOrDefault(elem => doc.GetElement(elem).get_BoundingBox(view) != null)
);
var b = f.get_BoundingBox(view);
var maxX = b.Max.X;
var maxY = b.Max.Y;
var maxZ = b.Max.Z;
var minX = b.Min.X;
var minY = b.Min.Y;
var minZ = b.Min.Z;
foreach (var elementId in elementIds)
{
var e = doc.GetElement(elementId);
var bb = e.get_BoundingBox(view);
if (b == null)//?莫名其妙等于空
{
continue;
}
if (bb.Max.X >= maxX)
{
maxX = bb.Max.X;
}
if (bb.Max.Y >= maxY)
{
maxY = bb.Max.Y;
}
if (bb.Max.Z >= maxZ)
{
maxZ = bb.Max.Z;
}
if (bb.Min.X <= minX)
{
minX = bb.Min.X;
}
if (bb.Min.Y <= minY)
{
minY = bb.Min.Y;
}
if (bb.Min.Z <= minZ)
{
minZ = bb.Min.Z;
}
}
var box = b.Extend(extendXyz);
//var max = new XYZ(maxX, maxY, maxZ) + b.Max.Normalize() * extendXyz;
//var min = new XYZ(minX, minY, minZ) - b.Min.Normalize() * extendXyz;
//b.Max = max;
//b.Min = min;
return box;
}
/// <summary>
/// 获取元素的包围框
/// </summary>
/// <param name="view"></param>
/// <param name="elementId"></param>
/// <param name="extendXyz"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="InvalidOperationException"></exception>
public static BoundingBoxXYZ GetElementBox(this View view, ElementId elementId, int extendXyz = 1)
{
if (view == null)
{
throw new ArgumentNullException(nameof(view), "视图为空");
}
var doc = view.Document;
var e = doc.GetElement(elementId);
if (!e.IsValidObject)
{
throw new InvalidOperationException("元素无效");
}
var b = e.get_BoundingBox(view);
if (b == null)//?莫名其妙等于空
{
return null;
}
var box = b.Extend(extendXyz);
return box;
}
/// <summary>
/// 恢复替换的外观
/// </summary>
/// <param name="view"></param>
/// <param name="elements"></param>
public static void ResetOverrideAppearance(this View view, List<Element> elements)
{
OverrideGraphicSettings overrideGraphicSettings = new();
foreach (var panel in elements)
{
view.SetElementOverrides(panel.Id, overrideGraphicSettings);
}
}
/// <summary>
/// 新建视图并设置剖切框,若无法剖切则返回用于复制的三维视图
/// </summary>
/// <param name="view3D">用于复制的三维视图</param>
/// <param name="elementId"></param>
/// <param name="inCurrentView">是否在当前视图创建</param>
/// <param name="extendXYZ"></param>
/// <returns></returns>
public static View3D SectionBoxElement(this View3D view3D, ElementId elementId, bool inCurrentView = true, int extendXYZ = 1)
{
var b = view3D.GetElementBox(elementId, extendXYZ);
if (b == null)
{
return view3D;
}
if (!view3D.IsSectionBoxActive)
{
view3D.IsSectionBoxActive = true;
}
if (inCurrentView)
{
view3D.SetSectionBox(b);
return view3D;
}
var viewCopyId = view3D.Duplicate(ViewDuplicateOption.WithDetailing);
var viewCopy = view3D.Document.GetElement(viewCopyId) as View3D;
viewCopy.DisplayStyle = DisplayStyle.ShadingWithEdges;
viewCopy.DetailLevel = ViewDetailLevel.Fine;
viewCopy?.SetSectionBox(b);
return viewCopy;
}
/// <summary>
/// 新建视图并设置剖切框,若无法剖切则返回用于复制的三维视图
/// </summary>
/// <param name="view3D">用于复制的三维视图</param>
/// <param name="elementIds"></param>
/// <param name="inCurrentView">是否在当前视图创建</param>
/// <param name="extendXYZ"></param>
/// <returns></returns>
public static View3D SectionBoxElements(this View3D view3D, List<ElementId> elementIds, bool inCurrentView = true, int extendXYZ = 1)
{
var b = view3D.GetElementsBox(elementIds, extendXYZ);
if (b == null)
{
return view3D;
}
if (!view3D.IsSectionBoxActive)
{
view3D.IsSectionBoxActive = true;
}
if (inCurrentView)
{
view3D.SetSectionBox(b);
return view3D;
}
var viewCopyId = view3D.Duplicate(ViewDuplicateOption.WithDetailing);
var viewCopy = view3D.Document.GetElement(viewCopyId) as View3D;
viewCopy.DisplayStyle = DisplayStyle.ShadingWithEdges;
viewCopy.DetailLevel = ViewDetailLevel.Fine;
viewCopy?.SetSectionBox(b);
return viewCopy;
}
/// <summary>
/// 设置图例位置
/// </summary>
/// <param name="legend"></param>
/// <param name="location"></param>
public static void SetLegendLocation(this View legend, XYZ location)
{
var doc = legend.Document;
var viewport = Viewport.Create(doc, doc.ActiveView.Id, legend.Id, XYZ.Zero);
if (viewport == null)
{
MessageBox.Show("视图中可能未包含图例所需的元素,请选择\r正确的图纸视口或图例命令来创建图例。", "温馨提示");
return;
}
var outline = viewport.GetBoxOutline();
var l = outline.MaximumPoint.X - outline.MinimumPoint.X;
var w = outline.MaximumPoint.Y - outline.MinimumPoint.Y;
var c = new XYZ(l / 2, w / 2, 0) + location;
viewport.SetBoxCenter(c);
var ele = doc.OfClass<ElementType>().FirstOrDefault(x => x.Name.Contains("无标题"));
viewport.ChangeTypeId(ele?.Id); //选择视口-无标题
}
/// <summary>
/// 已经打开的视图中缩放视图,最大化图元
/// </summary>
/// <param name="view"></param>
/// <param name="uidoc"></param>
/// <param name="elementIds"></param>
/// <param name="extend">扩宽范围</param>
public static void ZoomElements(this View view, UIDocument uidoc, List<ElementId> elementIds, int extend = 2)
{
var box = view.GetElementsBox(elementIds, extend);
if (box == null) return;
var uiView = uidoc.GetOpenUIViews().FirstOrDefault(v => v.ViewId == uidoc.ActiveGraphicalView.Id);
uiView?.ZoomAndCenterRectangle(box.Min, box.Max);
}
/// <summary>
/// 已经打开的视图中缩放视图,最大化图元
/// </summary>
/// <param name="view"></param>
/// <param name="uidoc"></param>
/// <param name="elementId"></param>
/// <param name="extend">扩宽范围</param>
public static void ZoomElement(this View view, UIDocument uidoc, ElementId elementId, int extend = 2)
{
var elem = uidoc.Document.GetElement(elementId);
if (!elem.IsValidObject || !elem.IsVisible(view)) return;
var box = elem.get_BoundingBox(view);
if (box == null) return;
box = box.Extend(extend);
var uiView = uidoc.GetOpenUIViews().FirstOrDefault(v => v.ViewId == uidoc.ActiveGraphicalView.Id);
uiView?.ZoomAndCenterRectangle(box.Min, box.Max);
}
#if REVIT2018
/// <summary>
/// </summary>
/// <param name="view"></param>
/// <param name="viewFilterName"></param>
/// <param name="rules"></param>
/// <param name="categoryIds">需要跟过滤规则对应,否则无效</param>
public static void CreateViewFilter(
this View view,
string viewFilterName,
List<FilterRule> rules,
ISet<ElementId> categoryIds
)
{
var doc = view.Document;
try
{
if (ParameterFilterElement.AllRuleParametersApplicable(doc, categoryIds, rules))
{
var filter = ParameterFilterElement.Create(doc, viewFilterName, categoryIds);
if (filter.AllRuleParametersApplicable(rules))
{
filter.SetRules(rules);
}
view.AddFilter(filter.Id);
var settings = view.GetFilterOverrides(filter.Id);
//view.SetCutLineColor(new SelectedColor(255, 0, 0));
settings.SetProjectionLineColor(new Color(255, 0, 0));
view.SetFilterOverrides(filter.Id, settings);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
#else
/// <summary>
/// </summary>
/// <param name="view"></param>
/// <param name="viewFilterName"></param>
/// <param name="logicalFilter"></param>
/// <param name="categoryIds">需要跟过滤规则对应,否则无效</param>
/// <param name="paramFilters"></param>
public static void CreateViewFilter(
this View view,
string viewFilterName,
ElementLogicalFilter logicalFilter,
ISet<ElementId> categoryIds,
params ElementParameterFilter[] paramFilters
)
{
var doc = view.Document;
List<ElementFilter> filters = new();
foreach (var filter in paramFilters)
{
filters.Add(filter);
}
logicalFilter.SetFilters(filters);
try
{
if (
ParameterFilterElement.ElementFilterIsAcceptableForParameterFilterElement(
doc,
categoryIds,
logicalFilter
)
)
{
var filter = ParameterFilterElement.Create(doc, viewFilterName, categoryIds);
if (filter.AllRuleParametersApplicable(logicalFilter))
{
filter.SetElementFilter(logicalFilter);
}
view.AddFilter(filter.Id);
var settings = view.GetFilterOverrides(filter.Id);
//view.SetCutLineColor(new SelectedColor(255, 0, 0));
settings.SetProjectionLineColor(new Color(255, 0, 0));
view.SetFilterOverrides(filter.Id, settings);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
#endif
}