using System; using System.Collections.Generic; using System.Linq; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using OfficeOpenXml.FormulaParsing.Excel.Functions.Math; namespace Szmedi.Toolkit.RvExtensions; public static class ElementExtensions { /// /// 容差 /// private const double Tolerance = 0.0001; /// /// 有类型定义的DirectShape /// /// /// 定义名称,即是族名称、类型名称(强制一致),创建多个实例时,如果相同,则会合并在一个族中 /// 族类别 /// 几何 /// public static DirectShape CreateDirectShapeInstance(this Document doc, string definitionId, BuiltInCategory category, List geos) { DirectShapeLibrary directShapeLibrary = DirectShapeLibrary.GetDirectShapeLibrary(doc); ElementId directShapeTypeId = directShapeLibrary.FindDefinitionType(definitionId); if (doc.GetElement(directShapeTypeId) == null) { var directShapeType = DirectShapeType.Create(doc, definitionId, new ElementId(category)); directShapeTypeId = directShapeType.Id; directShapeLibrary.AddDefinitionType(definitionId, directShapeTypeId); } //else //{ // directShapeLibrary.AddDefinition(definitionId, geos); //} var shape = DirectShape.CreateElementInstance(doc, directShapeTypeId, new ElementId(category), definitionId, Transform.Identity); //shape.SetTypeId(directShapeTypeId); shape.SetName(definitionId); shape.SetShape(geos); return shape; } /// /// 已经打开的视图中缩放视图,最大化图元 /// /// /// /// /// 扩宽范围 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); } public static bool IsVisible(this Element elem, View view) => FilteredElementCollector.IsViewValidForElementIteration(elem.Document, view.Id) && new FilteredElementCollector(elem.Document, view.Id).ToElementIds().Any(id => id == elem.Id); /// /// 无名称定义的DirectShape /// /// /// /// /// public static DirectShape CreateDirectShape(this Document doc, List geos, BuiltInCategory category) { var shape = DirectShape.CreateElement(doc, new ElementId(category)); shape.SetShape(geos); return shape; } /// /// 扩展包围盒的大小 /// /// /// /// public static BoundingBoxXYZ Extend(this BoundingBoxXYZ boundingBox, double distance = 2.0) { var transform = boundingBox.Transform; var max = boundingBox.Max + distance * (transform.BasisX + transform.BasisY + transform.BasisZ); var min = boundingBox.Min - distance * (transform.BasisX + transform.BasisY + transform.BasisZ); return new BoundingBoxXYZ() { Max = max, Min = min, Transform = transform }; } private static List GetGeoObjects(this GeometryObject geoObject) where T : GeometryObject { List geometryObjects = []; if (geoObject is Solid instSolid) { if (typeof(T) == typeof(Solid)) { geometryObjects.Add(instSolid as T); } if (typeof(T) == typeof(Face) && instSolid.Faces.Size > 0) { geometryObjects.AddRange(instSolid.Faces.Cast()); } else if (typeof(T) == typeof(Edge) && instSolid.Edges.Size > 0) { geometryObjects.AddRange(instSolid.Edges.Cast()); } } return geometryObjects; } /// /// 主次分支连接 /// /// 主管 /// 分支 public static void ConnectTo(this MEPCurve mainMepCurve, MEPCurve branchMepCurve) { var document = mainMepCurve.Document; var unboundBranchCurve = branchMepCurve.GetLocCurve(); unboundBranchCurve.MakeUnbound(); var unboundMainCurve = mainMepCurve.GetLocCurve(); unboundMainCurve.MakeUnbound(); var intersection = unboundBranchCurve.IntersectionPoint(unboundMainCurve) ?? throw new InvalidOperationException("主次分支管线不存在交点"); var line = mainMepCurve.GetLocCurve() as Line; //根据交点在管线内的位置,判断是形成弯头还是三通 if (line.IsInsideEx(intersection, 0.5)) //三通 { var newMainMEPCurveId = mainMepCurve.BreakByPoint(intersection); var newMainMEPCurve = document.GetElement(newMainMEPCurveId) as MEPCurve; var mainConnectors = ConnectorExtensions.GetNearestConnectors(mainMepCurve, newMainMEPCurve); var branchConnector = branchMepCurve.GetConnectors(true).GetNearestConnector(intersection); /* 项目“Szmedi.Toolkit (net48)”的未合并的更改 在此之前: branchConnector.ConnectByTee(mainConnectors[0], mainConnectors[1]); 在此之后: branchConnector.ConnectByTee(mainConnectors[0], mainConnectors[1]); */ branchConnector.ConnectByTee(mainConnectors[0], mainConnectors[1]); } else //弯头 { var conn = mainMepCurve.GetConnectors(true).GetNearestConnector(intersection); var conn2 = branchMepCurve.GetConnectors(true).GetNearestConnector(intersection); /* 项目“Szmedi.Toolkit (net48)”的未合并的更改 在此之前: conn.ConnectByFitting(conn2); 在此之后: conn.ConnectByFitting(conn2); */ conn.ConnectByFitting(conn2); } } public static HermiteSpline ConverToHermiteSpline(this PolyLine polyLine) { var list = polyLine.GetCoordinates(); return HermiteSpline.Create(list, false); } /// /* 项目“Szmedi.Toolkit (net48)”的未合并的更改 在此之前: /// 分支连接 /// /// /// /// /// public static FamilyInstance ConnectByTee(this Connector branch, Connector connector, Connector connector1) { doc doc = branch.Owner.doc; //获取垂直主管的向量 XYZ normal = connector.CoordinateSystem.BasisZ.CrossProduct(branch.CoordinateSystem.BasisZ); XYZ vertical = connector.CoordinateSystem.BasisZ.CrossProduct(normal); Line mainLine = Line.CreateUnbound(connector.Origin, connector.CoordinateSystem.BasisZ); Line branchLine = Line.CreateUnbound(branch.Origin, branch.CoordinateSystem.BasisZ); //分支和主管的角度 double cos = branch.CoordinateSystem.BasisZ.DotProduct(connector.CoordinateSystem.BasisZ); double angle = Math.Acos(cos); //主管和分支管的交点 XYZ intersect = mainLine.IntersectionPoint(branchLine); //垂直主管的分支管,为了创建默认三通 Line verticalLine = Line.CreateBound(intersect, intersect + (3.0 * vertical)); //延长管线到交点处 branch.Owner.SetLocationCurve((branch.Owner.GetLocCurve() as Line).ExtendLine(intersect)); connector.Owner.SetLocationCurve((connector.Owner.GetLocCurve() as Line).ExtendLine(intersect)); connector1.Owner.SetLocationCurve((connector1.Owner.GetLocCurve() as Line).ExtendLine(intersect)); //复制支管创建垂直主管的管线 ElementId verticalMEPCurveId = ElementTransformUtils.CopyElement(doc, branch.Owner.Id, XYZ.Zero).FirstOrDefault(); MEPCurve verticalMEPCurve = doc.GetElement(verticalMEPCurveId) as MEPCurve; verticalMEPCurve.SetLocationCurve(verticalLine); //获取垂直管的连接件 Connector tempBranchConnector = verticalMEPCurve.GetConnectors().GetNearestConnector(intersect); //创建三通 FamilyInstance tee = doc.Create.NewTeeFitting(connector, connector1, tempBranchConnector); if (tempBranchConnector.GetConnectedConnector().Owner.Id != tee.Id) { doc.Delete(tempBranchConnector.GetConnectedConnector().Owner.Id); } doc.Delete(verticalMEPCurveId); //三通中未连接的连接件即分支连接件 Connector teeBranchConn = tee.GetConnectors(true).OfType().FirstOrDefault(); try { //设置三通角度 teeBranchConn!.Angle = Math.PI - angle; } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { Debug.WriteLine("无法修改管线角度"); } doc.Regenerate(); //Connector branchFarConn = branch.Owner.GetConnectors().GetFarthestConnector(intersect); //Line newBranch = Line.CreateBound(branchFarConn.Origin, teeBranchConn.Origin); Line l = branch.Owner.GetLocCurve() as Line; Line newBranchLine = l.ExtendLine(teeBranchConn!.Origin); branch.Owner.SetLocationCurve(newBranchLine); //Line line = branch.Owner.GetLocCurve() as Line; //if (newBranch.Direction.IsAlmostEqualTo(line.Direction)) //{ // (branch.Owner.Location as LocationCurve).Curve = newBranch; //} //else if (newBranch.Direction.IsAlmostEqualTo(-line.Direction)) //{ // (branch.Owner.Location as LocationCurve).Curve = newBranch.CreateReversed(); //} Connector newBranchConn = GetNearestConnector(branch.Owner.GetConnectors(), intersect); newBranchConn.ConnectByFitting(teeBranchConn); return tee; } /// /// 新建视图并设置剖切框 在此之后: /// 新建视图并设置剖切框 */ /// /// 新建视图并设置剖切框 /// /// /// 复制的三维视图 /// /// public static View3D CreateSectionBox(this View3D view3D, IEnumerable elementIds, bool inCurrentView) { var doc = view3D.Document; XYZ extendXyz = new(1, 1, 1); BoundingBoxXYZ b; if (elementIds.Count() == 1) { var e = doc.GetElement(elementIds.FirstOrDefault()); b = e.get_BoundingBox(view3D); var max = b.Max + extendXyz; var min = b.Min - extendXyz; b = new BoundingBoxXYZ { Max = max, Min = min }; } else { var f = doc.GetElement(elementIds.FirstOrDefault(elem => doc.GetElement(elem).get_BoundingBox(view3D) != null)); b = f.get_BoundingBox(view3D); 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(doc.ActiveView); 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 max = new XYZ(maxX, maxY, maxZ) + extendXyz; var min = new XYZ(minX, minY, minZ) - extendXyz; b = new BoundingBoxXYZ { Max = max, Min = min }; } if (!view3D.IsSectionBoxActive) { view3D.IsSectionBoxActive = true; } if (inCurrentView) { view3D.SetSectionBox(b); return view3D; } var viewCopyId = view3D.Duplicate(ViewDuplicateOption.WithDetailing); var viewCopy = doc.GetElement(viewCopyId) as View3D; viewCopy?.SetSectionBox(b); return viewCopy; } public static double Distance(this Line line1, Line line2) { double distance; var v1 = line1.Direction; var p1 = line1.GetEndPoint(0); var v2 = line2.Direction; var p2 = line2.GetEndPoint(0); var a = p1.X - p2.X; var b = p1.Y - p2.Y; var c = p1.Z - p2.Z; var pq = v1.X * v2.Y - v2.X * v1.Y; var qr = v1.Y * v2.Z - v2.Y * v1.Z; var rp = v1.Z * v2.X - v2.Z * v1.X; var dev = Math.Sqrt(Math.Pow(qr, 2) + Math.Pow(rp, 2) + Math.Pow(pq, 2)); if (dev < 1e-9) { var bp = b * v1.X; var br = b * v1.Z; var cp = c * v1.X; var cq = c * v1.Y; var aq = a * v1.Y; var ar = a * v1.Z; distance = Math.Sqrt(Math.Pow(br - cq, 2) + Math.Pow(cp - ar, 2) + Math.Pow(aq - bp, 2)) / Math.Sqrt(Math.Pow(v1.X, 2) + Math.Pow(v1.Y, 2) + Math.Pow(v1.Z, 2)); } else { distance = Math.Abs((qr * a + rp * b + pq * c) / dev); } return distance; } /// /// 延长或缩短直线 /// /// /// /// 保留部分,为空时,保留长的部分 /// public static Line ExtendLine(this Line line, XYZ endPoint, bool? startSection = null) { var v = endPoint - line.GetEndPoint(0); var v2 = endPoint - line.GetEndPoint(1); //点刚好是直线端点 if (v.IsZeroLength() || v2.IsZeroLength()) { return line; } //必须平行才能延伸 if (v.IsParallelTo(v2)) { //点在直线外,同方向 if (line.Direction.DotProduct(v) > 0.0 && line.Direction.DotProduct(v2) > 0.0) { return Line.CreateBound(line.GetEndPoint(0), endPoint); } //点在直线外,反方向 if (line.Direction.DotProduct(v) < 0.0 && line.Direction.DotProduct(v2) < 0.0) { return Line.CreateBound(endPoint, line.GetEndPoint(1)); } //点在直线内 return v.DotProduct(v2) < 0.0 ? startSection == null ? v.GetLength() >= v2.GetLength() ? Line.CreateBound(line.GetEndPoint(0), endPoint) : Line.CreateBound(endPoint, line.GetEndPoint(1)) : startSection == true ? Line.CreateBound(line.GetEndPoint(0), endPoint) : Line.CreateBound(endPoint, line.GetEndPoint(1)) : null; } return line; //throw new InvalidOperationException("不可延伸到该点"); } /// /// 延长直线 /// /// /// /// 是否双向延申,单向延长终点 /// public static Line ExtendLine(this Line line, double distance, bool isInteractive = false) { var endPoint = line.GetEndPoint(1) + line.Direction * distance; var startPoint = line.GetEndPoint(0); if (isInteractive) { startPoint += line.Direction.Negate() * distance; } return Line.CreateBound(startPoint, endPoint); } /// /// 点拍平到xy平面 /// /// /// public static XYZ Flatten(this XYZ xyz) { return xyz.Subtract(XYZ.BasisZ * xyz.Z); } /// /// 点拍平到标高平面 /// /// /// public static XYZ FlattenTo(this XYZ xyz, Level level) { var z = level.Elevation; return xyz.Add(XYZ.BasisZ * (z - xyz.Z)); } /// /// 获取块参照实例 /// /// /// /// public static List GetBlockInstance(this ImportInstance dwg, Reference reference) { var geoElem = dwg.get_Geometry(new Options()); var geoObj = dwg.GetGeometryObjectFromReference(reference); GeometryInstance referBlock = null; foreach (var obj in geoElem) { if (obj is GeometryInstance dwgGeo) //dwg几何实例 { foreach (var block in dwgGeo.SymbolGeometry) //块 { if (block is GeometryInstance ins) { if (ins.GetHashCode() == geoObj.GetHashCode()) { referBlock = ins; break; } else { foreach (var subBlock in ins.SymbolGeometry) //嵌套块/子块 { if (subBlock is GeometryInstance subIns && subIns.GetHashCode() == geoObj.GetHashCode()) { referBlock = ins; break; } } } } } } } if (referBlock == null) { return null; } List blocks = []; foreach (var obj in geoElem) { if (obj is GeometryInstance dwgGeo) { foreach (var block in dwgGeo.SymbolGeometry) //图元 { if (block is GeometryInstance ins && ins.Symbol.Name == referBlock.Symbol.Name) { blocks.Add(ins); } } } } return blocks; } /// /// 得到元素所有连接件 /// /// /// 获取未使用的连接件,否则获取全部 /// public static ConnectorSet GetConnectors(this Element element, bool isUnused = false) { var connectorSet = new ConnectorSet(); switch (element) { case FamilyInstance familyInstance: connectorSet = isUnused ? familyInstance.MEPModel.ConnectorManager?.UnusedConnectors : familyInstance.MEPModel?.ConnectorManager?.Connectors; break; case MEPCurve mepCurve: connectorSet = isUnused ? mepCurve.ConnectorManager.UnusedConnectors : mepCurve.ConnectorManager.Connectors; break; case FabricationPart fabricationPart: connectorSet = isUnused ? fabricationPart.ConnectorManager.UnusedConnectors : fabricationPart.ConnectorManager.Connectors; break; } return connectorSet; } /// /// 获取dwg的曲线 /// /// /// public static List GetCurves(this ImportInstance importInstance) { List curves = []; var geoElem = importInstance.get_Geometry(new Options()); foreach (var geomObj in geoElem) { var geomInstance = geomObj as GeometryInstance; if (geomInstance != null) { foreach (var instObj in geomInstance.GetInstanceGeometry()) { //polyLine拆成线 if (instObj is PolyLine line) { var poly = line.GetCoordinates(); for (var i = 0; i < poly.Count - 1; i++) { var l = Line.CreateBound(poly[i], poly[i + 1]); curves.Add(l); } } if (instObj is Arc arc) { curves.Add(arc); } } } } return curves; } public static ElementId GetElementId(this BuiltInCategory builtInCategory, Document doc) { return Category.GetCategory(doc, builtInCategory).Id; } /// /// 获取顶层的几何(非嵌套) /// /// /// /// public static List GetGeometryObjects(this Element elem) { List geometryObjects = []; Options option = new() { ComputeReferences = true, DetailLevel = ViewDetailLevel.Fine }; var geometry = elem.get_Geometry(option); foreach (var geomObj in geometry) { geometryObjects.Add(geomObj); } return geometryObjects; } /// /// 获取几何对象 /// /// 对应类型的几何对象,如Solid、Face、Edge /// 获取的元素 /// public static List GetGeometryObjects(this Element elem) where T : GeometryObject { List geometryObjects = []; Options option = new() { ComputeReferences = true, DetailLevel = ViewDetailLevel.Fine }; var geometry = elem.get_Geometry(option); foreach (var geomObj in geometry) { if (geomObj is GeometryInstance geomInstance) { var usesSymbolGeometry = elem is FamilyInstance instance && !instance.HasModifiedGeometry(); var geometryElement = usesSymbolGeometry ? geomInstance.GetSymbolGeometry() : geomInstance.GetInstanceGeometry(); foreach (var geoObject in geometryElement) { geometryObjects.AddRange(geoObject.GetGeoObjects()); } } geometryObjects.AddRange(geomObj.GetGeoObjects()); } return geometryObjects; } /// /// 获取参考所在的图层名称 /// /// /// /// public static string GetLayerName(this ImportInstance dwg, Reference reference) { var obj = dwg.GetGeometryObjectFromReference(reference); var style = dwg.Document.GetElement(obj.GraphicsStyleId) as GraphicsStyle; return style?.GraphicsStyleCategory.Name; } /// /// 获取标高 /// /// /// public static ElementId GetLevelId(this Element model) { // 定义需要检查的参数列表 var parametersToCheck = new BuiltInParameter[] { BuiltInParameter.WALL_BASE_CONSTRAINT, // 墙 BuiltInParameter.SCHEDULE_BASE_LEVEL_PARAM, // 柱子标高 BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM, // 梁标高 BuiltInParameter.STAIRS_BASE_LEVEL_PARAM, // 楼梯标高 BuiltInParameter.INSTANCE_ELEVATION_PARAM, // 族实例明细表标高 BuiltInParameter.ROOF_CONSTRAINT_LEVEL_PARAM,//屋顶 BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM,// 族实例明细表标高 BuiltInParameter.RBS_START_LEVEL_PARAM// 管线标高 }; // 依次检查每个参数 foreach (var param in parametersToCheck) { var baseLevelId = model.get_Parameter(param)?.AsElementId(); if (baseLevelId != ElementId.InvalidElementId && baseLevelId != null) { return baseLevelId; } } //最后检查楼板或族基准标高 return model.LevelId; } /// /// 获取元素定位线 /// /// 以曲线定位的实例 /// public static Curve GetLocCurve(this Element instance) { return instance.Location is LocationCurve lc ? lc.Curve : null; } /// /// 获取元素定位点 /// /// 以点定位的实例 /// public static XYZ GetLocXYZ(this Element instance) { return instance.Location is LocationPoint lc ? lc.Point : null; } /// /// 同专业类型的最近连接件 /// /// /// /// /// public static List GetNearestDomainConnectors(Element element1, Element element2, bool isUnused = true) { List list = []; Connector conn = null; Connector conn2 = null; var distance = double.MaxValue; foreach (Connector connTemp in element1.GetConnectors(isUnused)) { foreach (Connector connTemp2 in element2.GetConnectors(isUnused)) { var tempDistance = connTemp.Origin.DistanceTo(connTemp2.Origin); if (connTemp.Domain == connTemp2.Domain && distance > tempDistance) { distance = tempDistance; conn = connTemp; conn2 = connTemp2; } } } if (conn != null) { list.Add(conn); } if (conn2 != null) { list.Add(conn2); } return list; } /// /// 计算两条线的交点 /// /// /// /// public static XYZ IntersectionPoint(this Curve curve1, Curve curve2) { var comparisonR = curve1.Intersect(curve2, out var intersectionR); XYZ intersectionResult = null; if (SetComparisonResult.Disjoint != comparisonR) // Disjoint无交点 { try { if (intersectionR != null && !intersectionR.IsEmpty) { intersectionResult = intersectionR.get_Item(0).XYZPoint; } } catch { // ignored } } return intersectionResult; } public static XYZ IntersectPoint(this Plane plane, Line line) { var startPoint = line.Origin; var projectPoint = plane.ProjectOnto(startPoint); if (Math.Abs(line.Direction.DotProduct(plane.Normal)) < 10E-8) //是否平行 { return null; } var length = startPoint.DistanceTo(projectPoint); if (length < 10E-8) //不平行,但刚好是Origin,即为交点 { return projectPoint; } var vector = projectPoint - startPoint; //var per = Line.CreateBound(startPoint, projectPoint);//垂线 if (vector.IsParallelTo(line.Direction)) { return projectPoint; } var cos = plane.Normal.DotProduct(line.Direction); if (cos < 0) { cos = plane.Normal.Negate().DotProduct(line.Direction); } var distance = length / cos; return vector.Normalize().DotProduct(line.Direction) < 0 ? startPoint - line.Direction * distance : startPoint + line.Direction * distance; } /// /// 点是否在直线范围内 /// /// /// /// 两边端点距离 /// public static bool IsInsideEx(this Line line, XYZ point, double endParameter = 0.0) { var flag = line == null; if (flag) { throw new ArgumentNullException(nameof(line)); } var isBound = line.IsBound; bool result; if (isBound) { var d = point.DistanceTo(line.GetEndPoint(0)); var d2 = point.DistanceTo(line.GetEndPoint(1)); result = d + d2 - line.Length < 1E-05 && d >= endParameter && d2 >= endParameter; } else { result = false; } return result; } /// /// 判断直线是否平行或重合 /// /// /// /// public static bool IsParallelTo(this Line line, Line checkedLine) { var a = line.Direction.CrossProduct(checkedLine.Direction).IsZeroLength(); var b = line.Direction.CrossProduct(checkedLine.Direction).IsAlmostEqualTo(XYZ.Zero); var c = 1 - Math.Abs(line.Direction.DotProduct(checkedLine.Direction)) < Tolerance; return a || b || c; } /// /// 判断方向是否平行 /// /// /// /// public static bool IsParallelTo(this XYZ direction1, XYZ direction2) { return direction1.CrossProduct(direction2).IsZeroLength() || direction1.CrossProduct(direction2).IsAlmostEqualTo(XYZ.Zero); } /// /// 判断直线是否垂直 /// /// /// /// /// public static bool IsPerpendicularTo(this Line line, Line checkedLine, double tolerance = Tolerance) { return Math.Abs(line.Direction.DotProduct(checkedLine.Direction)) < tolerance; //点乘满足交换律不影响计算结果 } /// /// 直线在平面上的投影 /// /// /// /// public static Line ProjectOnto(this Plane plane, Line line) { return Line.CreateBound(plane.ProjectOnto(line.GetEndPoint(0)), plane.ProjectOnto(line.GetEndPoint(1))); } /// /// 点在几何面的投影 /// /// /// /// public static XYZ ProjectOnto(this PlanarFace plane, XYZ p) { var d = plane.SignedDistanceTo(p, out _); var q = p - d * plane.FaceNormal; return q; } /// /// 点在参照平面上的投影 /// /// /// /// public static XYZ ProjectOnto(this Plane plane, XYZ p) { var d = plane.SignedDistanceTo(p, out _); var q = p - d * plane.Normal; return q; } public static void SetBorderColor(this Element element, Color color, View view = null) { var doc = element.Document; view ??= doc.ActiveView; var overrideGraphicSettings = view.GetElementOverrides(element.Id); var pat = new FilteredElementCollector(doc) .OfClass(typeof(FillPatternElement)) .ToElements() .Cast() .Where(pattern => { var fill = pattern.GetFillPattern(); return fill.Target == FillPatternTarget.Drafting && fill.HostOrientation == FillPatternHostOrientation.ToView && fill.IsSolidFill; }) .FirstOrDefault(); overrideGraphicSettings.SetProjectionLineColor(color); overrideGraphicSettings.SetCutLineColor(color); view.SetElementOverrides(element.Id, overrideGraphicSettings); } public static void SetFillColor(this Element element, Color color, View view = null) { var doc = element.Document; view ??= doc.ActiveView; var overrideGraphicSettings = view.GetElementOverrides(element.Id); var pat = new FilteredElementCollector(doc) .OfClass(typeof(FillPatternElement)) .ToElements() .Cast() .Where(pattern => { var fill = pattern.GetFillPattern(); return fill.Target == FillPatternTarget.Drafting && fill.HostOrientation == FillPatternHostOrientation.ToView && fill.IsSolidFill; }) .FirstOrDefault(); #if REVIT2018 overrideGraphicSettings.SetProjectionFillPatternId(pat.Id); overrideGraphicSettings.SetProjectionLineColor(color); overrideGraphicSettings.SetCutFillPatternId(pat.Id); overrideGraphicSettings.SetCutLineColor(color); view.SetElementOverrides(element.Id, overrideGraphicSettings); #elif REVIT2020 overrideGraphicSettings.SetSurfaceForegroundPatternColor(color); overrideGraphicSettings.SetSurfaceForegroundPatternId(pat.Id); //实体填充 overrideGraphicSettings.SetCutForegroundPatternColor(color); overrideGraphicSettings.SetCutForegroundPatternId(pat.Id); //实体填充 #endif } /// /// 设置元素定位线 /// /// /// /// public static void SetLocationCurve(this Element instance, Curve curve) { if (instance == null) { throw new ArgumentNullException(nameof(instance)); } if (curve == null) { throw new ArgumentNullException(nameof(curve)); } if (instance.Location is LocationCurve lc) { try { lc.Curve = curve; } catch (Exception) { throw new InvalidOperationException("无法修改定位线"); } } } /// /// 点与几何平面的距离(可正可负) /// /// /// /// /// public static double SignedDistanceTo(this PlanarFace plane, XYZ p, out XYZ projectPoint) { var v = p - plane.Origin; //垂向距离(可正可负,夹角钝角为负) var perp = v.DotProduct(plane.FaceNormal); projectPoint = p - perp * plane.FaceNormal; return perp; } /// /// 点与平面的距离(可正可负) /// /// /// /// /// public static double SignedDistanceTo(this Plane plane, XYZ p, out XYZ projectPoint) { var v = p - plane.Origin; //垂向距离(可正可负,夹角钝角为负) var perp = v.DotProduct(plane.Normal); projectPoint = p - perp * plane.Normal; return perp; } public static BuiltInCategory ToBuiltInCategory(this Category category) { var builtInCategory = (BuiltInCategory)category.Id.IntegerValue; return Enum.IsDefined(typeof(BuiltInCategory), builtInCategory) ? builtInCategory : throw new ArgumentNullException(nameof(category), "不存在该内建类别"); } public static Element ToElement(this ElementId id, Document doc) { return doc.GetElement(id); } }