280 lines
9.1 KiB
C#
280 lines
9.1 KiB
C#
using Autodesk.Revit.DB;
|
||
using Autodesk.Revit.DB.Architecture;
|
||
using ShrlAlgoToolkit.Core.Assists;
|
||
|
||
namespace ShrlAlgoToolkit.Revit.Extensions;
|
||
|
||
|
||
/// <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);
|
||
var solid = GeometryCreationUtilities.CreateExtrusionGeometry(curveLoops, XYZ.BasisZ, height, options);
|
||
|
||
var directShape = doc.CreateDirectShapeInstance(
|
||
"房间实体",
|
||
BuiltInCategory.OST_GenericModel,
|
||
[solid]);
|
||
directShape.get_Parameter(BuiltInParameter.DOOR_NUMBER).Set(room.Name);
|
||
//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 color = ColorAssist.GetDistinctColorById(directShape.Id);
|
||
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(directShape.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(directShape.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 directShape;
|
||
}
|
||
}
|