2025-04-24 20:56:44 +08:00
|
|
|
|
using Autodesk.Revit.DB;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
using Autodesk.Revit.UI;
|
2025-04-24 20:56:44 +08:00
|
|
|
|
|
|
|
|
|
|
using System.Windows;
|
|
|
|
|
|
|
|
|
|
|
|
namespace ShrlAlgoToolkit.Revit.Assists;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2024-10-27 00:19:48 +08:00
|
|
|
|
/// SectionView:
|
|
|
|
|
|
/// RightDirection = CropBox.Transform.BasisX;
|
|
|
|
|
|
/// ViewDirection = CropBox.Transform.BasisZ;
|
|
|
|
|
|
/// UpDirection = XYZ.BasisZ =CropBox.Transform.BasisY
|
2025-04-24 20:56:44 +08:00
|
|
|
|
public static class ViewExtensions
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
/// <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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <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
|
2025-04-24 20:56:44 +08:00
|
|
|
|
/// <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();
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
view.AddFilter(filter.Id);
|
|
|
|
|
|
var settings = view.GetFilterOverrides(filter.Id);
|
|
|
|
|
|
//view.SetCutLineColor(new SelectedColor(255, 0, 0));
|
|
|
|
|
|
settings.SetProjectionLineColor(new Color(255, 0, 0));
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
view.SetFilterOverrides(filter.Id, settings);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show(e.Message);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
#endif
|
|
|
|
|
|
}
|