using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Mechanical;
using FWindSoft.Revit;
using FWindSoft.Revit.Extension;
using FWindSoft.SystemExtensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LRH.Tool
{
public static class RoomToSpaceUtils
{
///
/// 获取指定的元素信息
///
///
///
///
public static List GetElements(View view, ElementFilter filter)
{
//删除当前视图下的所有空间和空间分割
var doc = view.Document;
var elements = doc.GetElements(filter);
return elements.Where(e => e.LevelId == view.GenLevel.Id).ToList();
}
///
/// 房间转换成空间
///
///
///
///
public static List RoomToSpace(View view, RoomToSpaceTransOption option,Transaction tran)
{
//删除当前视图下的所有空间和空间分割
var doc = view.Document;
var spaces = GetElements(view, new SpaceFilter());
if (option.DeleteOriginalSpace)
{
try
{
tran.Start();
doc.Delete(spaces.Select(e => e.Id).ToList());
tran.Commit();
}
catch (Exception)
{
tran.RollBack();
}
}
var spaceSeps = GetElements(view, new ElementCategoryFilter(BuiltInCategory.OST_MEPSpaceSeparationLines)).OfType().ToList();
if (option.DeleteOriginalSpaceSq)
{
try
{
tran.Start();
doc.Delete(spaceSeps.Select(e => e.Id).ToList());
tran.Commit();
}
catch (Exception)
{
tran.RollBack();
}
}
CreateSpaces(view, tran);
List relationItems = new List();
try
{
tran.Start();
#region 根据房间分割创建空间分割
if (option.RoomSqToSpaceSq)
{
var roomSeps = GetElements(view, new ElementCategoryFilter(BuiltInCategory.OST_RoomSeparationLines))
.OfType().ToList();
CurveArray curveArray = new CurveArray();
foreach (var roomSep in roomSeps)
{
curveArray.Append(roomSep.GeometryCurve);
}
if (!curveArray.IsEmpty)
{
Plane p = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin);
var sp = SketchPlane.Create(doc, p);
doc.Create.NewSpaceBoundaryLines(sp, curveArray, view);
}
}
#endregion
relationItems = RoomDataToSpace(view);
tran.Commit();
}
catch (Exception)
{
tran.RollBack();
}
return relationItems;
}
///
/// 房间数据转移到空间数据
///
///
///
public static List RoomDataToSpace(View view)
{
var doc = view.Document;
var rooms = GetElements(view, new RoomFilter()).OfType();
var offset = XYZ.BasisZ * 0.1;
HashSet handledSpaces = new HashSet();
List relations = new List();
foreach (Room room in rooms)
{
var relationItem = new RoomRelationItem() { RoomId = room.Id.ToString() };
relations.Add(relationItem);
using (SubTransaction subTran = new SubTransaction(doc))
{
Space useSpcae = null;
try
{
subTran.Start();
var location = room.Location.ConvertToPoint();
if (location == null )
{
//|| room.Area.IsEqual(0)
relationItem.Messages.Add("房间信息无效");
continue;
}
useSpcae = doc.GetSpaceAtPoint(location.Add(offset));
if (useSpcae == null)
{
relationItem.Messages.Add("未找到对应空间");
continue;
}
InfoTrans(room, useSpcae, handledSpaces.Contains(useSpcae.Id.IntegerValue));
subTran.Commit();
//成功
handledSpaces.Add(useSpcae.Id.IntegerValue);
relationItem.SpaceId = useSpcae.Id.ToString();
relationItem.IsSuccess = true;
}
catch (Exception ex)
{
relationItem.Messages.Add("赋值异常"+ex.Message);
subTran.RollBack();
}
}
}
return relations;
}
public static List CreateSpaces(View view)
{
List spaces = new List();
Document doc = view.Document;
var level = view.GenLevel;
Parameter para = view.GetParameter(BuiltInParameter.VIEW_PHASE);
ElementId phaseId = para.AsElementId();
var phase = doc.GetElement(phaseId) as Phase;
var points = GetSpacesPoints(view);
foreach (var point in points)
{
var oldSpace = doc.GetSpaceAtPoint(point, phase);
if (oldSpace == null)
{
var tempSapce = doc.Create.NewSpace(level, phase, new UV(point.X, point.Y));
spaces.Add(tempSapce);
}
}
return spaces;
}
public static void CreateSpaces(View view,Transaction tran)
{
Document doc = view.Document;
FailuresPreprocessor preprocessor = new FailuresPreprocessor(true);
{
try
{
FailureHandlingOptions fho = tran.GetFailureHandlingOptions();
fho.SetFailuresPreprocessor(preprocessor);
tran.SetFailureHandlingOptions(fho);
#region 创建空间
tran.Start();
var spaces=CreateSpaces(view);
tran.Commit(); //提交获取冲突代码
#endregion
#region 冲突处理代码
FailureHandlingOptions failureOptions = tran.GetFailureHandlingOptions();
failureOptions.SetFailuresPreprocessor(new FailuresPreprocessor(false));
tran.SetFailureHandlingOptions(failureOptions);
tran.Start();
//返回值临时使用
var failItems = preprocessor.Items;
foreach (var failuresItem in failItems)
{
var firstId = failuresItem.Items.FirstOrDefault();
if (firstId == null)
{
continue;
}
for (int i = 1; i < failuresItem.Items.Count; i++)
{
var currentId = failuresItem.Items[i];
if (firstId.IntegerValue > currentId.IntegerValue)
{
doc.Delete(new List() { firstId });
firstId = currentId;
}
} // doc.GetElement(failuresItem.Items.FirstOrDefault());
}
tran.Commit();
#endregion
}
catch (Exception ex)
{
tran.RollBack();
}
}
}
///
/// 获取视图中创建空间的点的信息
///
///
///
public static List GetSpacesPoints(View view)
{
Document doc = view.Document;
var level = view.GenLevel;
Parameter para = view.GetParameter(BuiltInParameter.VIEW_PHASE);
ElementId phaseId = para.AsElementId();
var phase = doc.GetElement(phaseId) as Phase;
#region 创建新的节点
List points = new List();
using (SubTransaction sub = new SubTransaction(doc))
{
try
{
sub.Start();
var spaceSeps = GetElements(view, new ElementCategoryFilter(BuiltInCategory.OST_MEPSpaceSeparationLines)).OfType().ToList();
CurveArray curveArray = new CurveArray();
foreach (var modelLine in spaceSeps)
{
curveArray.Append(modelLine.GeometryCurve);
}
#region 创建房间分割
Plane p = Plane.CreateByNormalAndOrigin(view.ViewDirection, view.Origin);
var sp = SketchPlane.Create(doc, p);
if (!curveArray.IsEmpty)
{
doc.Create.NewRoomBoundaryLines(sp, curveArray, view);
}
#endregion
#region 获取封闭区域
var topology = doc.get_PlanTopology(level, phase);
foreach (PlanCircuit topologyCircuit in topology.Circuits)
{
var point = topologyCircuit.GetPointInside();
var xyz = new XYZ(point.U, point.V, level.ProjectElevation + 1); //适当升高一些
points.Add(xyz);
}
#endregion
}
catch (Exception e)
{
}
finally
{
sub.RollBack();
}
}
#endregion
return points;
}
public static void InfoTrans(Room room,Space space,bool isAppend)
{
var name = room.GetParameterString(BuiltInParameter.ROOM_NAME) ?? string.Empty;
if (isAppend)
{
var oldName = space.GetParameterString(BuiltInParameter.ROOM_NAME)??string.Empty;
if (!string.IsNullOrWhiteSpace(name)&& !oldName.Contains(name))
{
name = oldName + "," + name;
}
}
space.SetParameter(BuiltInParameter.ROOM_NAME, name);
}
public static StringBuilder CreateResult(List items)
{
StringBuilder builder = new StringBuilder();
int errorCount = 0;
foreach (var item in items)
{
if (item.IsSuccess)
{
continue;
}
builder.AppendLine(item.ToString());
errorCount++;
}
builder.AppendLine($"总共{items.Count}房间,转换过程出现问题{errorCount}个");
return builder;
}
}
#region 扩展选项类
public class RoomRelationItem
{
public string RoomId { get; set; }
public string SpaceId { get; set; }
///
/// 是否成功
///
public bool IsSuccess { get; set; }
///
/// 错误消息
///
public List Messages { get; private set; } = new List();
public override string ToString()
{
var message = string.Join(";", Messages);
return $"RoomId:{RoomId} SpaceId:{SpaceId} Result:{message}";
}
}
///
/// 导出控制选项
///
public class RoomToSpaceTransOption
{
///
/// 是否删除原始空间
///
public bool DeleteOriginalSpace { get; set; } = true;
///
/// 是否删除原始空间分割
///
public bool DeleteOriginalSpaceSq { get; set; }
///
/// 是否将房间分割转换成空间分割
///
public bool RoomSqToSpaceSq { get; set; }
}
public class FailuresItem
{
public FailuresItem()
{
}
public FailuresItem(IEnumerable ids)
{
Items.AddRange(ids);
}
public List Items { get; private set; } = new List();
}
///
/// 空间错误机制
///
public class FailuresPreprocessor : IFailuresPreprocessor
{
/*
* 创建警告时,如果一个区域已经存在多个空间,创建警告时会把所有警告空间进行捕获
*/
#region 构造函数
public FailuresPreprocessor()
{
Items = new List();
}
public FailuresPreprocessor(bool append) : this()
{
Append = append;
}
#endregion
#region 相关操纵选项
///
/// 是否追加捕获信息
///
private bool Append { get; set; }
public void SetOperate(bool continueAdd)
{
Append = continueAdd;
}
public List Items { get; private set; }
#endregion
public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
{
IList messages = failuresAccessor.GetFailureMessages();
if (messages.Count == 0)
return FailureProcessingResult.Continue;
foreach (FailureMessageAccessor message in messages)
{
var currentSeverity = message.GetSeverity();
switch (currentSeverity)
{
case FailureSeverity.Error:
{
if (message.HasResolutions())
failuresAccessor.ResolveFailure(message);
break;
}
case FailureSeverity.Warning:
{
if (Append)
{
var elementIds = message.GetFailingElementIds();
if (elementIds.Any())
{
Items.Add(new FailuresItem(elementIds.ToList()));
}
}
failuresAccessor.DeleteWarning(message);
break;
}
}
}
return FailureProcessingResult.ProceedWithCommit;
}
}
#endregion
}