Files

871 lines
30 KiB
C#
Raw Permalink Normal View History

2024-09-22 11:05:41 +08:00
using Autodesk.Revit.DB;
2026-02-21 16:31:24 +08:00
using ShrlAlgoToolkit.RevitCore.Assists;
namespace ShrlAlgoToolkit.RevitCore.Extensions;
2025-04-24 20:56:44 +08:00
public static class WallExtensions
2024-09-22 11:05:41 +08:00
{
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>
2026-02-12 21:29:00 +08:00
/// 获取墙体的所有平面
2024-09-22 11:05:41 +08:00
/// </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);
}
2025-04-24 20:56:44 +08:00
2024-09-22 11:05:41 +08:00
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
}