319 lines
14 KiB
C#
319 lines
14 KiB
C#
|
|
|
|||
|
|
|
|||
|
|
using Autodesk.Revit.DB;
|
|||
|
|
using Autodesk.Revit.DB.IFC;
|
|||
|
|
using Autodesk.Revit.UI;
|
|||
|
|
|
|||
|
|
using System;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Windows;
|
|||
|
|
|
|||
|
|
|
|||
|
|
namespace Szmedi.RvKits.ModelManager
|
|||
|
|
{
|
|||
|
|
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
|
|||
|
|
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
|
|||
|
|
public class SplitComponentByLevelCmd : IExternalCommand
|
|||
|
|
{
|
|||
|
|
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
|
|||
|
|
{
|
|||
|
|
var result=MessageBox.Show("确认按标高拆分墙柱构件?", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
|||
|
|
if (result != MessageBoxResult.Yes)
|
|||
|
|
{
|
|||
|
|
return Result.Cancelled;
|
|||
|
|
}
|
|||
|
|
var uiapp = commandData.Application;
|
|||
|
|
var uidoc = uiapp.ActiveUIDocument;
|
|||
|
|
var doc = uidoc.Document;
|
|||
|
|
var view = doc.ActiveView;
|
|||
|
|
var instances = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).Cast<FamilyInstance>();
|
|||
|
|
List<MessageModel> elementsToSkip = [];
|
|||
|
|
using (TransactionGroup tg = new(doc, "按标高拆分墙、柱"))
|
|||
|
|
{
|
|||
|
|
tg.Start();
|
|||
|
|
//墙打断
|
|||
|
|
using (Transaction trans = new(doc, "楼层分割打断构件"))
|
|||
|
|
{
|
|||
|
|
trans.Start();
|
|||
|
|
var levels = doc.OfClass<Level>()
|
|||
|
|
.OfCategory(BuiltInCategory.OST_Levels)
|
|||
|
|
.Cast<Level>()
|
|||
|
|
.OrderBy(l => l.Elevation)
|
|||
|
|
.ToList();
|
|||
|
|
|
|||
|
|
var walls = doc.OfType<Wall>().ToList();
|
|||
|
|
var structuralColumns = doc.OfClass<FamilyInstance>().OfCategory(BuiltInCategory.OST_StructuralColumns).ToList();
|
|||
|
|
var columns = doc.OfClass<FamilyInstance>().OfCategory(BuiltInCategory.OST_Columns).ToList();
|
|||
|
|
List<ElementId> elemToSplitIds = [];
|
|||
|
|
foreach (var wall in walls)
|
|||
|
|
{
|
|||
|
|
//得到墙的包围框
|
|||
|
|
var canModify = true;
|
|||
|
|
foreach (var instance in instances)
|
|||
|
|
{
|
|||
|
|
if (instance.Host != null && instance.Host.Id == wall.Id)
|
|||
|
|
{
|
|||
|
|
elementsToSkip.Add(new MessageModel(wall, "主体不存在"));
|
|||
|
|
canModify = false;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (ExporterIFCUtils.HasElevationProfile(wall))
|
|||
|
|
{
|
|||
|
|
canModify = false;
|
|||
|
|
}
|
|||
|
|
var needToDelete = false;
|
|||
|
|
if (canModify)
|
|||
|
|
{
|
|||
|
|
needToDelete = SplitWallByLevel(doc, wall, view);
|
|||
|
|
}
|
|||
|
|
if (needToDelete)
|
|||
|
|
{
|
|||
|
|
elemToSplitIds.Add(wall.Id);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
foreach (FamilyInstance column in structuralColumns)
|
|||
|
|
{
|
|||
|
|
var canModify = true;
|
|||
|
|
foreach (var instance in instances)
|
|||
|
|
{
|
|||
|
|
if (instance.Host != null && instance.Host.Id == column.Id)
|
|||
|
|
{
|
|||
|
|
elementsToSkip.Add(new MessageModel(column, "主体不存在"));
|
|||
|
|
canModify = false;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
var needToDelete = false;
|
|||
|
|
if (canModify)
|
|||
|
|
{
|
|||
|
|
needToDelete = SplitColumnByLevel(doc, column, view);
|
|||
|
|
}
|
|||
|
|
if (needToDelete)
|
|||
|
|
{
|
|||
|
|
elemToSplitIds.Add(column.Id);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
foreach (FamilyInstance column in columns)
|
|||
|
|
{
|
|||
|
|
var canModify = true;
|
|||
|
|
foreach (var instance in instances)
|
|||
|
|
{
|
|||
|
|
if (instance.Host != null && instance.Host.Id == column.Id)
|
|||
|
|
{
|
|||
|
|
elementsToSkip.Add(new MessageModel(column, "主体不存在"));
|
|||
|
|
canModify = false;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
var needToDelete = false;
|
|||
|
|
if (canModify)
|
|||
|
|
{
|
|||
|
|
needToDelete = SplitColumnByLevel(doc, column, view);
|
|||
|
|
}
|
|||
|
|
if (needToDelete)
|
|||
|
|
{
|
|||
|
|
elemToSplitIds.Add(column.Id);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
doc.Delete(elemToSplitIds);
|
|||
|
|
trans.Commit();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
tg.Assimilate();
|
|||
|
|
}
|
|||
|
|
if (elementsToSkip.Count > 0)
|
|||
|
|
{
|
|||
|
|
//AssemblyLoaderHelpers loader = new(GlobalVariables.DirAssembly);
|
|||
|
|
//loader.HookAssemblyResolve();
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
MessageWin errorResolveWin = new()
|
|||
|
|
{
|
|||
|
|
DataContext = new MessageViewModel(uidoc, elementsToSkip)
|
|||
|
|
};
|
|||
|
|
errorResolveWin.ShowDialog();
|
|||
|
|
}
|
|||
|
|
catch (Exception e)
|
|||
|
|
{
|
|||
|
|
MessageBox.Show(e.Message); LogAssists.WriteLog(e.StackTrace);
|
|||
|
|
}
|
|||
|
|
//finally
|
|||
|
|
//{
|
|||
|
|
// loader.UnhookAssemblyResolve();
|
|||
|
|
//}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
MessageBox.Show("处理完成", "处理结果", MessageBoxButton.OK, MessageBoxImage.Information);
|
|||
|
|
}
|
|||
|
|
return Result.Succeeded;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private static bool SplitColumnByLevel(Document doc, FamilyInstance column, View view)
|
|||
|
|
{
|
|||
|
|
var wallBox = column.get_BoundingBox(view);
|
|||
|
|
var minZ = wallBox.Min.Z;
|
|||
|
|
var maxZ = wallBox.Max.Z;
|
|||
|
|
var allLevels = new FilteredElementCollector(doc)
|
|||
|
|
.OfClass(typeof(Level))
|
|||
|
|
.OfCategory(BuiltInCategory.OST_Levels)
|
|||
|
|
.Cast<Level>()
|
|||
|
|
.OrderBy(o => o.Elevation)
|
|||
|
|
.ToList();
|
|||
|
|
var toSplit = new FilteredElementCollector(doc)
|
|||
|
|
.OfClass(typeof(Level))
|
|||
|
|
.OfCategory(BuiltInCategory.OST_Levels)
|
|||
|
|
.Cast<Level>()
|
|||
|
|
.Where(l => l.Elevation - minZ > 0.0001 && maxZ - l.Elevation > 0.0001)
|
|||
|
|
.OrderBy(o => o.Elevation)
|
|||
|
|
.ToList();
|
|||
|
|
|
|||
|
|
if (toSplit.Count == 0)
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var n = allLevels.FindIndex(l => l.Id == toSplit.First().Id);
|
|||
|
|
var minLevel = allLevels.First();
|
|||
|
|
if (n > 0)
|
|||
|
|
{
|
|||
|
|
minLevel = allLevels[n - 1]; //存在更低的标高时,取此标高作为底标高约束
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
XYZ translation = new();
|
|||
|
|
|
|||
|
|
var bottomEleIds = ElementTransformUtils.CopyElement(doc, column.Id, translation);
|
|||
|
|
var minWall = doc.GetElement(bottomEleIds.FirstOrDefault()) as FamilyInstance;
|
|||
|
|
//底部约束
|
|||
|
|
minWall.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).Set(minLevel.Id);
|
|||
|
|
minWall.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(minZ - minLevel.Elevation);
|
|||
|
|
minWall.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).Set(toSplit.First().Id);
|
|||
|
|
minWall.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(0);
|
|||
|
|
|
|||
|
|
var maxLevel = toSplit.Last();
|
|||
|
|
var m = allLevels.FindIndex(l => l.Id == toSplit.Last().Id);
|
|||
|
|
if (m < allLevels.Count - 1)
|
|||
|
|
{
|
|||
|
|
maxLevel = allLevels[m + 1]; //存在更高的标高
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var topEleIds = ElementTransformUtils.CopyElement(doc, column.Id, translation);
|
|||
|
|
var maxWall = doc.GetElement(topEleIds.FirstOrDefault()) as FamilyInstance;
|
|||
|
|
|
|||
|
|
maxWall.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).Set(toSplit.Last().Id);
|
|||
|
|
maxWall.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(0);
|
|||
|
|
maxWall.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).Set(maxLevel.Id);
|
|||
|
|
maxWall.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(maxZ - maxLevel.Elevation);
|
|||
|
|
|
|||
|
|
for (var i = 0; i < toSplit.Count - 1; i++)
|
|||
|
|
{
|
|||
|
|
var baseLevel = toSplit[i];
|
|||
|
|
var topLevel = toSplit[i + 1];
|
|||
|
|
var eleIds = ElementTransformUtils.CopyElement(doc, column.Id, translation);
|
|||
|
|
var wallCopy = doc.GetElement(eleIds.FirstOrDefault()) as FamilyInstance;
|
|||
|
|
wallCopy.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).Set(baseLevel.Id);
|
|||
|
|
wallCopy.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(0);
|
|||
|
|
|
|||
|
|
wallCopy.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).Set(topLevel.Id);
|
|||
|
|
wallCopy.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(0);
|
|||
|
|
//if (i == levelsToSplit.Count - 2 && maxZ < maxLevel.Elevation)
|
|||
|
|
//{
|
|||
|
|
// wallCopy.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - maxLevel.Elevation);
|
|||
|
|
//}
|
|||
|
|
//Wall.Create(doc, curve, wall.WallType.Id, levels[i].Id, 100, 100, false, false);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 切分墙体
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="doc"></param>
|
|||
|
|
/// <param name="wall"></param>
|
|||
|
|
/// <param name="view">三维视图</param>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
private static bool SplitWallByLevel(Document doc, Wall wall, View view)
|
|||
|
|
{
|
|||
|
|
var wallBox = wall.get_BoundingBox(view);
|
|||
|
|
var minZ = wallBox.Min.Z;
|
|||
|
|
var maxZ = wallBox.Max.Z;
|
|||
|
|
var allLevels = new FilteredElementCollector(doc)
|
|||
|
|
.OfClass(typeof(Level))
|
|||
|
|
.OfCategory(BuiltInCategory.OST_Levels)
|
|||
|
|
.Cast<Level>()
|
|||
|
|
.OrderBy(o => o.Elevation)
|
|||
|
|
.ToList();
|
|||
|
|
var toSplit = new FilteredElementCollector(doc)
|
|||
|
|
.OfClass(typeof(Level))
|
|||
|
|
.OfCategory(BuiltInCategory.OST_Levels)
|
|||
|
|
.Cast<Level>()
|
|||
|
|
.Where(l => l.Elevation - minZ > 0.0001 && maxZ - l.Elevation > 0.0001)
|
|||
|
|
.OrderBy(o => o.Elevation)
|
|||
|
|
.ToList();
|
|||
|
|
|
|||
|
|
if (toSplit.Count == 0)
|
|||
|
|
{
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var n = allLevels.FindIndex(l => l.Id == toSplit.First().Id);
|
|||
|
|
var minLevel = allLevels.First();
|
|||
|
|
if (n > 0)
|
|||
|
|
{
|
|||
|
|
minLevel = allLevels[n - 1]; //存在更低的标高时,取此标高作为底标高约束
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
XYZ translation = new();
|
|||
|
|
|
|||
|
|
var bottomEleIds = ElementTransformUtils.CopyElement(doc, wall.Id, translation);
|
|||
|
|
var minWall = doc.GetElement(bottomEleIds.FirstOrDefault()) as Wall;
|
|||
|
|
//底部约束
|
|||
|
|
minWall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(minLevel.Id);
|
|||
|
|
minWall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(minZ - minLevel.Elevation);
|
|||
|
|
minWall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(toSplit.First().Id);
|
|||
|
|
minWall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(0);
|
|||
|
|
|
|||
|
|
var maxLevel = toSplit.Last();
|
|||
|
|
var m = allLevels.FindIndex(l => l.Id == toSplit.Last().Id);
|
|||
|
|
if (m < allLevels.Count - 1)
|
|||
|
|
{
|
|||
|
|
maxLevel = allLevels[m + 1]; //存在更高的标高
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var topEleIds = ElementTransformUtils.CopyElement(doc, wall.Id, translation);
|
|||
|
|
var maxWall = doc.GetElement(topEleIds.FirstOrDefault()) as Wall;
|
|||
|
|
|
|||
|
|
maxWall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(toSplit.Last().Id);
|
|||
|
|
maxWall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(0);
|
|||
|
|
maxWall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(maxLevel.Id);
|
|||
|
|
maxWall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - maxLevel.Elevation);
|
|||
|
|
|
|||
|
|
for (var i = 0; i < toSplit.Count - 1; i++)
|
|||
|
|
{
|
|||
|
|
var baseLevel = toSplit[i];
|
|||
|
|
var topLevel = toSplit[i + 1];
|
|||
|
|
var eleIds = ElementTransformUtils.CopyElement(doc, wall.Id, translation);
|
|||
|
|
var wallCopy = doc.GetElement(eleIds.FirstOrDefault()) as Wall;
|
|||
|
|
wallCopy.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(baseLevel.Id);
|
|||
|
|
wallCopy.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(0);
|
|||
|
|
|
|||
|
|
wallCopy.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(topLevel.Id);
|
|||
|
|
wallCopy.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(0);
|
|||
|
|
//if (i == levelsToSplit.Count - 2 && maxZ < maxLevel.Elevation)
|
|||
|
|
//{
|
|||
|
|
// wallCopy.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - maxLevel.Elevation);
|
|||
|
|
//}
|
|||
|
|
//Wall.Create(doc, curve, wall.WallType.Id, levels[i].Id, 100, 100, false, false);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|