Files
Shrlalgo.RvKits/ShrlAlgoToolkit.Revit/Extensions/RoomExtensions.cs
2025-07-12 23:31:32 +08:00

285 lines
9.4 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 Autodesk.Revit.DB.Architecture;
namespace ShrlAlgoToolkit.Revit.Assists;
/// <summary>
/// 房间类的扩展
/// </summary>
/// <remarks>
/// <para>房间的边界外圈是逆时针,所有内圈是顺时针,墙体相交会导致边界线被切分</para>
///<para>底部偏移 item.Room.BaseOffset = baseOffset;</para>
///<para>高度偏移 item.Room.LimitOffset = baseOffset;</para>
///<para>全部高度 item.Room.UnboundedHeight顶部-底部;</para>
/// </remarks>
public static class RoomExtensions
{
/// <summary>
/// 墙饰面
/// </summary>
/// <param name="room"></param>
/// <param name="height"></param>
/// <param name="newWallType"></param>
/// <returns>墙饰面与房间边界的字典</returns>
public static Dictionary<ElementId, ElementId> CreateWalls(this Room room, double height, WallType newWallType)
{
var doc = newWallType.Document;
var dictionary = new Dictionary<ElementId, ElementId>();
var levelId = room.LevelId;
var boundarySegments = room.GetBoundarySegments(
new SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish }
);
if (boundarySegments == null)
{
return dictionary;
}
foreach (var list in boundarySegments)
{
if (list.Count == 0)
{
continue;
}
foreach (var boundarySegment in list)
{
var element = doc.GetElement(boundarySegment.ElementId);
if (element == null)
{
continue;
}
var category = doc.Settings.Categories.get_Item(BuiltInCategory.OST_RoomSeparationLines);
if (element.Category.Id == category.Id)
{
continue;
}
var wall = Wall.Create(doc, boundarySegment.GetCurve(), newWallType.Id, levelId, height, 0.0, false, false);
wall.get_Parameter(BuiltInParameter.WALL_KEY_REF_PARAM).Set(2);
dictionary.Add(wall.Id, boundarySegment.ElementId);
}
}
return dictionary;
}
/// <summary>
/// 创建房间的内建模型
/// </summary>
/// <param name="room"></param>
/// <returns></returns>
public static DirectShape CreateSolid(this Room room)
{
return RoomSolid(room, room.GetBoundaryCurveLoops());
}
/// <summary>
/// 得到房间边界的线串
/// </summary>
/// <param name="room"></param>
/// <returns></returns>
public static List<CurveLoop> GetBoundaryCurveLoops(this Room room)
{
var boundary = room.GetBoundarySegments(Options());
var list = new List<CurveLoop>();
if (boundary.Count != 0)
{
foreach (var list2 in boundary)
{
var curveLoop = new CurveLoop();
foreach (var boundarySegment in list2)
{
curveLoop.Append(boundarySegment.GetCurve());
}
list.Add(curveLoop);
}
}
return list;
}
/// <summary>
/// 房间边界组成的元素集合
/// </summary>
/// <param name="room"></param>
/// <returns></returns>
public static List<Element> GetBoundaryElementList(this SpatialElement room)
{
if (room is null)
{
throw new ArgumentNullException(nameof(room));
}
var results = new List<Element>();
var segments = room.GetBoundarySegments(Options()).SelectMany(s => s);
foreach (var segment in segments)
{
if (segment.ElementId == ElementId.InvalidElementId)
{
continue;
}
if (results.FirstOrDefault(f => f.Id == segment.ElementId) != null)
{
continue;
}
var elm = room.Document.GetElement(segment.ElementId);
results.Add(elm);
}
return results;
}
/// <summary>
/// 房间边界的对应字典(元素-曲线)集合
/// </summary>
/// <param name="room"></param>
/// <returns></returns>
public static Dictionary<Element, Curve> GetElementCurveDict(this Room room)
{
if (room is null)
{
throw new ArgumentNullException(nameof(room));
}
var doc = room.Document;
if (doc is null)
{
throw new ArgumentNullException(nameof(doc));
}
var segments = room.GetBoundarySegments(Options()).SelectMany(s => s);
return segments.ToDictionary(k => doc.GetElement(k.ElementId), v => v.GetCurve());
}
/// <summary>
/// 获取房间几何体相交的元素
/// </summary>
/// <param name="room"></param>
/// <returns></returns>
public static FilteredElementCollector GetIntersectElements(this Room room)
{
var doc = room.Document;
var solid = new SpatialElementGeometryCalculator(doc).CalculateSpatialElementGeometry(room).GetGeometry();
ElementIntersectsSolidFilter filter = new(solid);
return new FilteredElementCollector(doc).WherePasses(filter);
}
/// <summary>
/// 获取房间最外侧边界
/// </summary>
/// <param name="room"></param>
/// <returns></returns>
public static CurveArray GetOuterBoundary(this Room room)
{
var allCurves = new CurveArray();
var boundarySegments = room.GetBoundarySegments(Options()).First();
foreach (var bs in boundarySegments)
{
allCurves.Append(bs.GetCurve());
}
return allCurves;
}
private static SpatialElementBoundaryOptions Options()
{
return new SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish };
}
/// <summary>
/// 获取房间的几何体
/// </summary>
/// <param name="room"></param>
/// <returns></returns>
public static Solid GetSolid(this Room room)
{
var doc = room.Document;
var segc = new SpatialElementGeometryCalculator(doc);
var segr = segc.CalculateSpatialElementGeometry(room);
return segr.GetGeometry();
}
/// <summary>
/// 得到房间的三维实体
/// </summary>
/// <param name="room"></param>
/// <param name="curveLoops"></param>
/// <param name="material"></param>
/// <returns></returns>
private static DirectShape RoomSolid(Room room, List<CurveLoop> curveLoops, Material material = null)
{
var doc = room.Document;
var height = room.get_Parameter(BuiltInParameter.ROOM_HEIGHT).AsDouble();
var options =
material == null
? new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId)
: new SolidOptions(material.Id, ElementId.InvalidElementId);
options = new SolidOptions(material.Id, ElementId.InvalidElementId);
var solid = GeometryCreationUtilities.CreateExtrusionGeometry(curveLoops, XYZ.BasisZ, height);
var directShape = doc.CreateDirectShapeInstance(
"房间实体",
BuiltInCategory.OST_GenericModel,
new List<GeometryObject> { solid });
directShape.get_Parameter(BuiltInParameter.DOOR_NUMBER).Set(room.Name);
var ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
//ds.SetName(room.Name);
//var option = ds.GetOptions();
//option.ReferencingOption = DirectShapeReferencingOption.NotReferenceable;
//ds.SetOptions(option);
//ds.AppendShape(new List<GeometryObject> { solid });
//room.Document.Regenerate();
var elements = new FilteredElementCollector(doc);
var solidFillPattern = elements.OfClass(typeof(FillPatternElement)).Cast<FillPatternElement>().First(a => a.GetFillPattern().IsSolidFill);
var random = new Random(DateTime.Now.Millisecond);
var r = Convert.ToByte(random.Next(0, 255));
var g = Convert.ToByte(random.Next(0, 255));
var b = Convert.ToByte(random.Next(0, 255));
var color = new Color(r, g, b);
var ogs = new OverrideGraphicSettings();
ogs.SetProjectionLineColor(color);
#if REVIT2018
ogs.SetSurfaceTransparency(50);
ogs.SetProjectionFillColor(color);
ogs.SetProjectionFillPatternId(solidFillPattern.Id);
ogs.SetCutFillColor(color);
ogs.SetCutFillPatternId(solidFillPattern.Id);
doc.ActiveView.SetElementOverrides(ds.Id, ogs);
#else
ogs.SetSurfaceBackgroundPatternColor(color);
ogs.SetSurfaceForegroundPatternId(solidFillPattern.Id);
ogs.SetSurfaceForegroundPatternColor(color);
ogs.SetCutBackgroundPatternColor(color);
ogs.SetCutForegroundPatternColor(color);
ogs.SetCutForegroundPatternId(solidFillPattern.Id);
ogs.SetSurfaceTransparency(50);
doc.ActiveView.SetElementOverrides(ds.Id, ogs);
#endif
//foreach (Face face in solid.Faces)
//{
// room.Document.Paint(ds.Id,,);
// //PlanarFace pf = face as PlanarFace;
// //if (pf.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ))
// //{
// // array.Append(face);
// // break;
// //}
//}
return ds;
}
}