Files
ShrlAlgoToolkit/ShrlAlgoToolkit.Revit/Extensions/WallExtensions.cs
2026-02-17 22:17:13 +08:00

870 lines
30 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Autodesk.Revit.DB;
using ShrlAlgoToolkit.Revit.Assists;
namespace ShrlAlgoToolkit.Revit.Extensions;
public static class WallExtensions
{
private static List<Edge> GetEdges(this Wall wall)
{
var edges = new List<Edge>();
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<Edge>());
}
return edges;
}
private static List<Solid> GetSolids(this Wall wall)
{
var solids = new List<Solid>();
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;
}
/// <summary>
/// 墙分隔条
/// </summary>
/// <param name="wall"></param>
/// <param name="wallSweepTypeName"></param>
/// <param name="distance"></param>
/// <param name="vertical"></param>
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);
}
}
/// <summary>
/// 获取嵌入墙体和连接墙体的图元,如相交的墙,已连接的柱,端点连接的墙
/// </summary>
/// <param name="wall"></param>
public static List<ElementId> FindElementsByOverlapFace(this Wall wall)
{
var joinedElements = new List<ElementId>();
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;
}
/// <summary>
/// 获取墙体的所有平面
/// </summary>
/// <param name="wall"></param>
/// <returns></returns>
public static List<PlanarFace> GetFaces(this Wall wall)
{
var planes = new List<PlanarFace>();
var list = wall.FindInserts(true, false, false, false);
var options = new Options { IncludeNonVisibleObjects = true, ComputeReferences = true };
var list2 = new List<string>();
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<double>();
foreach (var planarFace in wall.GetFaces())
{
list.Add(planarFace.GetMaxX());
}
return list.Max();
}
public static double GetMaxY(this Wall wall)
{
var list = new List<double>();
foreach (var planarFace in wall.GetFaces())
{
list.Add(planarFace.GetMaxY());
}
return list.Max();
}
public static double GetMaxZ(this Wall wall)
{
var list = new List<double>();
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<double>();
foreach (var planarFace in wall.GetFaces())
{
list.Add(planarFace.GetMinX());
}
return list.Min();
}
public static double GetMinY(this Wall wall)
{
var list = new List<double>();
foreach (var advancedPlanarFace in wall.GetFaces())
{
list.Add(advancedPlanarFace.GetMinY());
}
return list.Min();
}
public static double GetMinZ(this Wall wall)
{
var list = new List<double>();
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();
}
/// <summary>
/// 为墙体分层设置材料
/// </summary>
/// <param name="wall"></param>
/// <param name="layerIndex"></param>
/// <param name="newMat"></param>
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<Wall> 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);
}
}
}
/// <summary>
/// 获取外墙
/// </summary>
/// <param name="walls"></param>
/// <returns></returns>
public static List<Wall> GetOuterWalls(IReadOnlyList<Wall> walls)
{
var list = new List<Wall>();
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<Wall>();
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<Wall> walls, Wall wall)
{
return walls.Any(w => w.Id == wall.Id);
}
public static bool IsAdjoinToByLocationCurveEnds(this Wall wall, Wall checkedWall)
{
var list = new List<string>();
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<PlanarFace> FilterFaces(
ExtremeWallVariant extremeWallVariant,
List<Wall> sideWalls,
IEnumerable<PlanarFace> selectedFaces
)
{
var num = 0.0001;
var doc = sideWalls.FirstOrDefault().Document;
var list = new List<PlanarFace>();
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<PlanarFace>();
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;
}
/// <summary>
/// 获取相交和相连的墙体
/// </summary>
/// <param name="sideWalls"></param>
/// <param name="allWalls"></param>
/// <returns></returns>
private static IEnumerable<Wall> FindIntersectionWalls(List<Wall> sideWalls, List<Wall> allWalls)
{
var list = new List<Wall>();
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<Wall> sideWalls,
List<Wall> allWalls,
ExtremeWallVariant extremeWallVariant,
bool intersectingWalls,
bool isOpenings,
ref ReferenceArray referenceArray
)
{
var list = new List<PlanarFace>();
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<string>();
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
}