using Autodesk.Revit.DB; using ShrlAlgoToolkit.RevitCore.Assists; namespace ShrlAlgoToolkit.RevitCore.Extensions; public static class WallExtensions { private static List GetEdges(this Wall wall) { var edges = new List(); var options = new Options { ComputeReferences = true }; foreach (var geometryObject in wall.get_Geometry(options).GetTransformed(Transform.Identity)) { var solid = geometryObject as Solid; if (solid == null) { continue; } edges.AddRange(solid.Edges.Cast()); } return edges; } private static List GetSolids(this Wall wall) { var solids = new List(); var options = new Options { ComputeReferences = true }; foreach (var geometryObject in wall.get_Geometry(options).GetTransformed(Transform.Identity)) { var solid = geometryObject as Solid; if (solid != null && solid.Volume > 0.0) { solids.Add(solid); } } return solids; } /// /// 墙分隔条 /// /// /// /// /// public static void CreateWallSweep(this Wall wall, string wallSweepTypeName, double distance, bool vertical) { var wallSweepType = new FilteredElementCollector(wall.Document) .OfCategory(BuiltInCategory.OST_Reveals) .WhereElementIsElementType() .FirstOrDefault(w => w.Name.Contains(wallSweepTypeName)); var info = new WallSweepInfo(WallSweepType.Reveal, vertical) { Distance = distance, WallSide = WallSide.Exterior, DistanceMeasuredFrom = DistanceMeasuredFrom.Base }; if (WallSweep.WallAllowsWallSweep(wall)) { if (wallSweepType != null) WallSweep.Create(wall, wallSweepType.Id, info); } } /// /// 获取嵌入墙体和连接墙体的图元,如相交的墙,已连接的柱,端点连接的墙 /// /// public static List FindElementsByOverlapFace(this Wall wall) { var joinedElements = new List(); var geometryElement = wall.get_Geometry(new Options()); foreach (var geometryObject in geometryElement) { if (geometryObject is not Solid solid) continue; foreach (Face face in solid.Faces) { var generatingElementIds = wall.GetGeneratingElementIds(face); generatingElementIds.Remove(wall.Id); foreach (var id in generatingElementIds.Where(id => !joinedElements.Contains(id))) { joinedElements.Add(id); } } } return joinedElements; } /// /// 获取墙体的所有平面 /// /// /// public static List GetFaces(this Wall wall) { var planes = new List(); var list = wall.FindInserts(true, false, false, false); var options = new Options { IncludeNonVisibleObjects = true, ComputeReferences = true }; var list2 = new List(); foreach (var solid in wall.GetSolids()) { foreach (Face face in solid.Faces) { var planarFace = face as PlanarFace; var orientation = (wall.Location as LocationCurve).Curve.GetElementOrientation(); if (planarFace == null) continue; if (planarFace.Reference != null) { if ((wall.GetEdges().Count > 0 && orientation == ElementOrientation.Horizontal) || orientation == ElementOrientation.Vertical) { planes.Add(planarFace); } } else { foreach (var elementId in wall.GetGeneratingElementIds(planarFace)) { if (elementId == wall.Id || list2.Any(s => s == elementId.ToString())) continue; if (!list.Contains(elementId)) continue; var element = wall.Document.GetElement(elementId); foreach (var geometryObject in element.get_Geometry(options).GetTransformed(Transform.Identity)) { var solid2 = geometryObject as Solid; if (solid2 == null) continue; foreach (var obj3 in solid2.Faces) { var face2 = (Face)obj3; var planarFace2 = face2 as PlanarFace; if (planarFace2 == null || planarFace2.Reference == null) continue; if ( (wall.GetEdges().Count > 0 && orientation == ElementOrientation.Horizontal) || orientation == ElementOrientation.Vertical ) { planes.Add(planarFace2); list2.Add(elementId.ToString()); } } } } } } } return planes; } public static double GetMaxX(this Wall wall) { var list = new List(); foreach (var planarFace in wall.GetFaces()) { list.Add(planarFace.GetMaxX()); } return list.Max(); } public static double GetMaxY(this Wall wall) { var list = new List(); foreach (var planarFace in wall.GetFaces()) { list.Add(planarFace.GetMaxY()); } return list.Max(); } public static double GetMaxZ(this Wall wall) { var list = new List(); foreach (var planarFace in wall.GetFaces()) { foreach (var edge in planarFace.GetEdges()) { var endPoint = edge.AsCurve().GetEndPoint(0); var endPoint2 = edge.AsCurve().GetEndPoint(1); if (!list.Contains(endPoint.Z)) { list.Add(endPoint.Z); } var flag2 = !list.Contains(endPoint2.Z); if (flag2) { list.Add(endPoint2.Z); } } } return list.Max(); } public static double GetMinX(this Wall wall) { var list = new List(); foreach (var planarFace in wall.GetFaces()) { list.Add(planarFace.GetMinX()); } return list.Min(); } public static double GetMinY(this Wall wall) { var list = new List(); foreach (var advancedPlanarFace in wall.GetFaces()) { list.Add(advancedPlanarFace.GetMinY()); } return list.Min(); } public static double GetMinZ(this Wall wall) { var list = new List(); foreach (var planarFace in wall.GetFaces()) { foreach (var edge in planarFace.GetEdges()) { var endPoint = edge.AsCurve().GetEndPoint(0); var endPoint2 = edge.AsCurve().GetEndPoint(1); if (!list.Contains(endPoint.Z)) { list.Add(endPoint.Z); } if (!list.Contains(endPoint2.Z)) { list.Add(endPoint2.Z); } } } return list.Min(); } /// /// 为墙体分层设置材料 /// /// /// /// public static void SetMaterialForWall(this Wall wall, int layerIndex, Material newMat) { // 得到墙体的复合结构(CompoundStructure)实例 var wallType = wall.WallType; var compoundStructure = wallType.GetCompoundStructure(); // 得到墙体第一层材料的元素Id var layer = compoundStructure.GetLayers().ElementAt(layerIndex); // 为墙体第一层设置一个新材料 layer.MaterialId = newMat.Id; } #region 静态方法 public static void FilterByCutPlan(List walls, ViewPlan view) { var viewRange = view.GetViewRange(); //视图平面剖面高度 var viewPlanCutPlaneElevation = viewRange.GetOffset(0) + view.GenLevel.ProjectElevation; for (var i = walls.Count - 1; i >= 0; i--) { if (viewPlanCutPlaneElevation < walls[i].GetMinZ() || viewPlanCutPlaneElevation > walls[i].GetMaxZ()) { walls.RemoveAt(i); } } } /// /// 获取外墙 /// /// /// public static List GetOuterWalls(IReadOnlyList walls) { var list = new List(); for (var i = 0; i < walls.Count; i++) { var wall = walls[i]; var curve = (wall.Location as LocationCurve)?.Curve; var startPoint = curve?.GetEndPoint(0); var midPoint = curve?.Evaluate(0.5, true); var endPoint = curve?.GetEndPoint(0); if (wall.Orientation.DotProduct(XYZ.BasisX) < 0.0001) { var line = Line.CreateBound(new XYZ(midPoint.X - 1000000.0, midPoint.Y, 0.0), new XYZ(midPoint.X, midPoint.Y, 0.0)); var line2 = Line.CreateBound(new XYZ(midPoint.X, midPoint.Y, 0.0), new XYZ(midPoint.X + 1000000.0, midPoint.Y, 0.0)); var flag2 = false; var flag3 = false; for (var j = 0; j < walls.Count; j++) { var wall1 = walls[j]; var curve1 = (wall1.Location as LocationCurve)?.Curve; var startPoint1 = curve1.GetEndPoint(0); var midPoint1 = curve1.Evaluate(0.5, true); var endPoint1 = curve1.GetEndPoint(0); if (i != j) { var flag5 = walls[j] == null; if (!flag5) { var checkedLine = Line.CreateBound(new XYZ(startPoint1.X, startPoint1.Y, 0.0), new XYZ(endPoint1.X, endPoint1.Y, 0.0)); if (line.Intersect(checkedLine) == SetComparisonResult.Overlap) { flag2 = true; } if (line2.Intersect(checkedLine) == SetComparisonResult.Overlap) { flag3 = true; } } } } if (flag2 ^ flag3) { list.Add(wall); } } if (wall.Orientation.DotProduct(XYZ.BasisY) < 0.0001) { var line3 = Line.CreateBound(new XYZ(midPoint.X, midPoint.Y + 1000000.0, 0.0), new XYZ(midPoint.X, midPoint.Y, 0.0)); var line4 = Line.CreateBound(new XYZ(midPoint.X, midPoint.Y, 0.0), new XYZ(midPoint.X, midPoint.Y - 1000000.0, 0.0)); var flag10 = false; var flag11 = false; for (var k = 0; k < walls.Count; k++) { if (i != k) { var wall1 = walls[k]; var curve1 = (wall1.Location as LocationCurve)?.Curve; var startPoint1 = curve1.GetEndPoint(0); var midPoint1 = curve1.Evaluate(0.5, true); var endPoint1 = curve1.GetEndPoint(0); var checkedLine2 = Line.CreateBound(new XYZ(startPoint1.X, startPoint1.Y, 0.0), new XYZ(endPoint1.X, endPoint1.Y, 0.0)); if (line3.Intersect(checkedLine2) == SetComparisonResult.Overlap) { flag10 = true; } if (line4.Intersect(checkedLine2) == SetComparisonResult.Overlap) { flag11 = true; } } } if (flag10 ^ flag11) { list.Add(wall); } } } var list2 = (from wall in list select wall.Id.ToString()).ToList(); var list3 = new List(); foreach (var wall in walls) { if (!list2.Any(s => s == wall.Id.ToString())) { var flag17 = false; var flag18 = false; foreach (var wall3 in list) { var flag19 = wall.IsAdjoinToByLocationCurveEnds(wall3, 0) && wall3.IsAdjoinToByLocationCurveEnds(wall); if (flag19) { flag17 = true; } var flag20 = wall.IsAdjoinToByLocationCurveEnds(wall3, 1) && wall3.IsAdjoinToByLocationCurveEnds(wall); if (flag20) { flag18 = true; } } if (flag17 && flag18) { list3.Add(wall); } } } list.AddRange(list3); return list; } public static double GetViewPlanCutPlaneElevation(ViewPlan viewPlan) { var viewRange = viewPlan.GetViewRange(); return viewRange.GetOffset(0) + viewPlan.GenLevel.ProjectElevation; } public static bool HasWallInListById(IEnumerable walls, Wall wall) { return walls.Any(w => w.Id == wall.Id); } public static bool IsAdjoinToByLocationCurveEnds(this Wall wall, Wall checkedWall) { var list = new List(); var elementArray = ((LocationCurve)wall.Location).get_ElementsAtJoin(0); var elementArray2 = ((LocationCurve)wall.Location).get_ElementsAtJoin(1); if (!elementArray2.IsEmpty) { foreach (var obj in elementArray2) { var element = (Element)obj; if (element is Wall && !wall.Id.Equals(element.Id)) { list.Add(element.Id.ToString()); } } } if (!elementArray.IsEmpty) { list.AddRange( from Element element2 in elementArray where element2 is Wall && !wall.Id.Equals(element2.Id) select element2.Id.ToString() ); } return list.Any(s => s == checkedWall.Id.ToString()); } public static void SetMaterial(this WallType wallType, int layIndex, Material material) { var compound = wallType.GetCompoundStructure(); if (compound == null) { throw new NullReferenceException("结构分层为空"); } compound.SetMaterialId(layIndex, material.Id); wallType.SetCompoundStructure(compound); } public static void SetWallLayerThickness(this WallType wallType, int layIndex, double thickness) { var compound = wallType.GetCompoundStructure(); if (compound == null) { throw new NullReferenceException("结构分层为空"); } compound.SetLayerWidth(layIndex, thickness / 304.8); wallType.SetCompoundStructure(compound); } private static IEnumerable FilterFaces( ExtremeWallVariant extremeWallVariant, List sideWalls, IEnumerable selectedFaces ) { var num = 0.0001; var doc = sideWalls.FirstOrDefault().Document; var list = new List(); var cutPlanZ = GetViewPlanCutPlaneElevation(doc.ActiveView as ViewPlan); foreach (var face in selectedFaces) { if (face.GetMinZ() <= cutPlanZ && face.GetMaxZ() >= cutPlanZ) { list.Add(face); } } var list2 = new List(); bool flag2; do { flag2 = list.Any(f => f != null); for (var i = 0; i < list.Count; i++) { if (list[i] != null) { list2.Add(list[i]); for (var j = 0; j < list.Count; j++) { if (i == j) { continue; } if (list[j] == null) { continue; } if (extremeWallVariant is ExtremeWallVariant.Left or ExtremeWallVariant.Right) { if (Math.Abs(list[i].Origin.Y - list[j].Origin.Y) < num) { list[j] = null; } } else { if (extremeWallVariant is not ExtremeWallVariant.Top and not ExtremeWallVariant.Bottom) { continue; } if (Math.Abs(list[i].Origin.X - list[j].Origin.X) < num) { list[j] = null; } } } list[i] = null; } } } while (flag2); var num2 = (from w in sideWalls select w.Width).Max() * 2.0; if (extremeWallVariant == ExtremeWallVariant.Bottom) { foreach (var wall in from w in sideWalls where w.Orientation.DotProduct(XYZ.BasisY) < 0.0001 select w) { for (var k = list2.Count - 1; k >= 0; k--) { var planarFace3 = list2[k]; var flag11 = planarFace3.GetMinX() > wall.GetMinX() - wall.Width && planarFace3.GetMinX() < wall.GetMaxX() + wall.Width; if (flag11 && planarFace3.GetMinY() > wall.GetMinY() + num2) { list2.RemoveAt(k); } } } } if (extremeWallVariant == ExtremeWallVariant.Top) { foreach (var wall in from w in sideWalls where w.Orientation.DotProduct(XYZ.BasisY) < 0.0001 select w) { for (var l = list2.Count - 1; l >= 0; l--) { if (list2[l].GetMinX() > wall.GetMinX() - wall.Width && list2[l].GetMinX() < wall.GetMaxX() + wall.Width) { if (list2[l].GetMaxY() < wall.GetMaxY() - num2) { list2.RemoveAt(l); } } } } } if (extremeWallVariant == ExtremeWallVariant.Left) { foreach (var wall in from w in sideWalls where w.Orientation.DotProduct(XYZ.BasisX) < 0.0001 select w) { for (var m = list2.Count - 1; m >= 0; m--) { if (list2[m].GetMinY() > wall.GetMinY() - wall.Width && list2[m].GetMinY() < wall.GetMaxY() + wall.Width) { if (list2[m].GetMinX() > wall.GetMinX() + num2) { list2.RemoveAt(m); } } } } } if (extremeWallVariant == ExtremeWallVariant.Right) { foreach (var wall in from w in sideWalls where w.Orientation.DotProduct(XYZ.BasisX) < 0.0001 select w) { for (var n = list2.Count - 1; n >= 0; n--) { if (list2[n].GetMinY() > wall.GetMinY() - wall.Width && list2[n].GetMinY() < wall.GetMaxY() + wall.Width) { if (list2[n].GetMaxX() < wall.GetMaxX() - num2) { list2.RemoveAt(n); } } } } } //int num4; //int num3 = int.TryParse(UserConfigFile.GetValue("mprExteriorPlanDimensions", "ExteriorFaceMinWidthBetween"), out num4) ? num4 : 100; var num3 = 100; var num5 = num3.ToFeet(); //int num6 = int.TryParse(UserConfigFile.GetValue("mprExteriorPlanDimensions", "ExteriorMinWidthFaceRemove"), out num4) ? num4 : 0; var num6 = 0; if (extremeWallVariant is ExtremeWallVariant.Bottom or ExtremeWallVariant.Top) { list2.Sort((f1, f2) => f1.GetMinX().CompareTo(f2.GetMinX())); var flag23 = false; do { for (var num7 = 0; num7 < list2.Count - 1; num7++) { var planarFace7 = list2[num7]; var planarFace8 = list2[num7 + 1]; var num8 = Math.Abs(planarFace7.GetMinX() - planarFace8.GetMinX()); if (num8 < num5) { flag23 = true; var num9 = Math.Abs(planarFace7.GetMaxY() - planarFace7.GetMinY()); var num10 = Math.Abs(planarFace8.GetMaxY() - planarFace8.GetMinY()); if (num6 == 0) { if (num9 < num10) { list2.RemoveAt(num7); } else { list2.RemoveAt(num7 + 1); } } else { if (num9 > num10) { list2.RemoveAt(num7); } else { list2.RemoveAt(num7 + 1); } } break; } flag23 = false; } } while (flag23); } if (extremeWallVariant is ExtremeWallVariant.Left or ExtremeWallVariant.Right) { list2.Sort((f1, f2) => f1.GetMinY().CompareTo(f2.GetMinY())); var flag29 = false; do { for (var num11 = 0; num11 < list2.Count - 1; num11++) { var planarFace9 = list2[num11]; var planarFace10 = list2[num11 + 1]; var num12 = Math.Abs(planarFace9.GetMinY() - planarFace10.GetMinY()); if (num12 < num5) { flag29 = true; var num13 = Math.Abs(planarFace9.GetMaxX() - planarFace9.GetMinX()); var num14 = Math.Abs(planarFace10.GetMaxX() - planarFace10.GetMinX()); if (num6 == 0) { if (num13 < num14) { list2.RemoveAt(num11); } else { list2.RemoveAt(num11 + 1); } } else { if (num13 > num14) { list2.RemoveAt(num11); } else { list2.RemoveAt(num11 + 1); } } break; } flag29 = false; } } while (flag29); } return list2; } /// /// 获取相交和相连的墙体 /// /// /// /// private static IEnumerable FindIntersectionWalls(List sideWalls, List allWalls) { var list = new List(); foreach (var wall in allWalls) { list.AddRange( from checkedWall in sideWalls where wall.IsAdjoinToByLocationCurveEnds(checkedWall) && !HasWallInListById(sideWalls, wall) select wall ); } return list; } private static void GetWallsReferences( List sideWalls, List allWalls, ExtremeWallVariant extremeWallVariant, bool intersectingWalls, bool isOpenings, ref ReferenceArray referenceArray ) { var list = new List(); var list2 = (from w in sideWalls where w.Orientation.DotProduct(XYZ.BasisX) < 0.0001 select w).ToList(); var list3 = (from w in sideWalls where w.Orientation.DotProduct(XYZ.BasisY) < 0.0001 select w).ToList(); if (!list2.Any() && !list3.Any()) { return; } if (!intersectingWalls) { if (extremeWallVariant is ExtremeWallVariant.Right or ExtremeWallVariant.Left) { foreach (var wall in sideWalls) { var list4 = wall.GetFaces().Where(face => face.IsHorizontal()).ToList(); list4.Sort((f1, f2) => f1.Origin.Y.CompareTo(f2.Origin.Y)); list.Add(list4.First()); list.Add(list4.Last()); } } if (extremeWallVariant is ExtremeWallVariant.Top or ExtremeWallVariant.Bottom) { foreach (var wall in sideWalls) { var list5 = wall.GetFaces().Where(face => face.IsVertical()).ToList(); list5.Sort((f1, f2) => f1.Origin.X.CompareTo(f2.Origin.X)); list.Add(list5.First()); list.Add(list5.Last()); } } } else { if (extremeWallVariant is ExtremeWallVariant.Right or ExtremeWallVariant.Left) { foreach (var wall in list3) { var list6 = wall.GetFaces().Where(face => face.IsHorizontal()).ToList(); list6.Sort((f1, f2) => f1.Origin.Y.CompareTo(f2.Origin.Y)); list.Add(list6.First()); list.Add(list6.Last()); } var list7 = ( from w in FindIntersectionWalls(sideWalls, allWalls) where w.Orientation.DotProduct(XYZ.BasisY) < 0.0001 select w ).ToList(); foreach (var wall in list7) { var list8 = wall.GetFaces().Where(face => face.IsHorizontal()).ToList(); list8.Sort((f1, f2) => f1.Origin.Y.CompareTo(f2.Origin.Y)); list.Add(list8.First()); list.Add(list8.Last()); } } if (extremeWallVariant is ExtremeWallVariant.Bottom or ExtremeWallVariant.Top) { foreach (var wall in list2) { var list9 = wall.GetFaces().Where(planarFace5 => planarFace5.IsVertical()).ToList(); list9.Sort((f1, f2) => f1.Origin.X.CompareTo(f2.Origin.X)); list.Add(list9.First()); list.Add(list9.Last()); } var list10 = ( from w in FindIntersectionWalls(sideWalls, allWalls) where w.Orientation.DotProduct(XYZ.BasisX) < 0.0001 select w ).ToList(); foreach (var wall in list10) { var list11 = wall.GetFaces().Where(face => face.IsVertical()).ToList(); list11.Sort((f1, f2) => f1.Origin.Y.CompareTo(f2.Origin.Y)); list.Add(list11.First()); list.Add(list11.Last()); } } } if (isOpenings) { if (extremeWallVariant is ExtremeWallVariant.Right or ExtremeWallVariant.Left) { foreach (var wall in list2) { list.AddRange(wall.GetFaces().Where(face => face.IsHorizontal())); } } if (extremeWallVariant is ExtremeWallVariant.Bottom or ExtremeWallVariant.Top) { foreach (var wall in list3) { list.AddRange(wall.GetFaces().Where(planarFace8 => planarFace8.IsVertical())); } } } var enumerable = FilterFaces(extremeWallVariant, sideWalls, list); foreach (var face in enumerable) { referenceArray.Append(face.Reference); } } private static bool IsAdjoinToByLocationCurveEnds(this Wall wall, Wall checkedWall, int end) { var list = new List(); var elementArray = ((LocationCurve)wall.Location).get_ElementsAtJoin(end); if (!elementArray.IsEmpty) { list.AddRange( from object obj in elementArray let element = (Element)obj where element is Wall && !wall.Id.ToString().Equals(element.Id.ToString()) select element.Id.ToString() ); } return list.Any(s => s == checkedWall.Id.ToString()); } #endregion }