Files
ShrlAlgoToolkit/ShrlAlgoToolkit.RevitAddins/ModelManager/CorrectReferLevelExecutes.cs
2026-02-20 16:47:26 +08:00

398 lines
16 KiB
C#

using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using ShrlAlgoToolkit.RevitAddins.Windows;
namespace ShrlAlgoToolkit.RevitAddins.ModelManager;
public class CorrectReferLevelExecutes
{
public CorrectReferLevelExecutes(UIApplication uiapp)
{
var uidoc = uiapp.ActiveUIDocument;
doc = uidoc.Document;
view = uidoc.ActiveView;
levels =doc.OfClass<Level>()
.OfCategory(BuiltInCategory.OST_Levels)
.Cast<Level>()
.OrderBy(l => l.Elevation)
.ToList();
levelOutlines = GetRegions(levels);
}
private readonly Document doc;
private readonly Dictionary<Level, Outline> levelOutlines;
private readonly List<Level> levels;
//private uiApplication uiApplication;
private readonly View view;
/// <summary>
/// 设置族实例
/// </summary>
/// <returns></returns>
public List<MessageModel> SetInstances()
{
List<MessageModel> errors = [];
doc.Invoke(_ =>
{
//对比标高,得到实际分层位置
foreach (var keyPair in levelOutlines)
{
//得到在标高范围内的元素
BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value);
var level = keyPair.Key;
var insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem is FamilyInstance && (elem.LevelId != level.Id || elem.get_BoundingBox(view) != null)).ToList();
foreach (var elem in insideCollector)
{
try
{
//获取构件定位方式,基于标高,基于主体(基于面,基于线,基于主体构件:墙板等),基于点
if (elem is not FamilyInstance familyInstance)
{
continue;
}
var placementType = familyInstance.Symbol.Family.FamilyPlacementType;
switch (placementType)
{
case FamilyPlacementType.OneLevelBased:
ModifyOneLevelBasedFamily(doc, level, familyInstance);
break;
case FamilyPlacementType.OneLevelBasedHosted:
break;
case FamilyPlacementType.TwoLevelsBased:
ModifyTwoLevelBasedFamily(doc, levels, level, familyInstance);
break;
case FamilyPlacementType.ViewBased:
break;
case FamilyPlacementType.WorkPlaneBased:
ModifyWorkPlaneBasedFamily(doc, level, familyInstance);
break;
case FamilyPlacementType.CurveBased:
ModifyCurveBasedFamily(doc, level, familyInstance);
break;
case FamilyPlacementType.CurveBasedDetail:
break;
case FamilyPlacementType.CurveDrivenStructural:
break;
case FamilyPlacementType.Adaptive:
break;
case FamilyPlacementType.Invalid:
break;
}
}
catch (Exception ex)
{
errors.Add(new MessageModel(elem, ex.Message));
}
}
}
}, "校正族实例标高");
return errors;
//if (errors.Any())
//{
// var processorViewModel = new ErrorResolveViewModel(UiDocument, errors);
// var errorResolveWin = new ErrorResolveWin(processorViewModel);
// WinDialogAssist.ShowAhead(errorResolveWin);
//}
}
/// <summary>
/// 设置管线
/// </summary>
/// <returns></returns>
public List<MessageModel> SetMEPCurves()
{
List<MessageModel> errors = [];
doc.Invoke(_ =>
{
//对比标高,得到实际分层位置
foreach (var keyPair in levelOutlines)
{
//得到在标高范围内的元素
BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value);
var level = keyPair.Key;
var insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem.LevelId != level.Id || elem.get_BoundingBox(view) != null).ToList();
foreach (var elem in insideCollector)
{
try
{
if (elem is Pipe or Duct or CableTray or Conduit)
{
elem.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).Set(level.Id);
}
}
catch (Exception ex)
{
errors.Add(new MessageModel(elem, ex.Message));
}
}
}
}, "校正管线标高");
return errors;
}
/// <summary>
/// 设置墙
/// </summary>
/// <returns></returns>
public List<MessageModel> SetWalls()
{
List<MessageModel> errors = [];
doc.Invoke(_ =>
{
//对比标高,得到实际分层位置
foreach (var keyPair in levelOutlines)
{
//得到在标高范围内的元素
BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value);
var level = keyPair.Key;
var insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem.LevelId != level.Id || elem.get_BoundingBox(view) != null).ToList();
foreach (var elem in insideCollector)
{
try
{
if (elem is Wall)
{
ModifyWall(view, levels, level, elem);
}
}
catch (Exception ex)
{
errors.Add(new MessageModel(elem, ex.Message));
}
}
}
}, "校正墙体标高");
return errors;
//if (errors.Any())
//{
// var processorViewModel = new ErrorResolveViewModel(UiDocument, errors);
// var errorResolveWin = new ErrorResolveWin(processorViewModel);
// WinDialogAssist.ShowAhead(errorResolveWin);
//}
}
/// <summary>
/// 获取基于标高的边界
/// </summary>
/// <param name="levels"></param>
/// <returns></returns>
public static Dictionary<Level, Outline> GetRegions(IEnumerable<Level> levels)
{
Dictionary<Level, Outline> levelOutlines = [];
////获取标高范围
for (var i = 0; i < levels.Count() - 1; i++)
{
var baseLevel = levels.ElementAt(i);
var topLevel = levels.ElementAt(i + 1);
XYZ min = new(double.MinValue, double.MinValue, baseLevel.Elevation);
XYZ max = new(double.MaxValue, double.MaxValue, topLevel.Elevation);
Outline outline = new(min, max);
levelOutlines.Add(baseLevel, outline);
}
return levelOutlines;
}
/// <summary>
/// 修改基于线的族
/// </summary>
/// <param name="doc"></param>
/// <param name="level"></param>
/// <param name="familyInstance"></param>
private static void ModifyCurveBasedFamily(Document doc, Level level, FamilyInstance familyInstance)
{
var originOffset = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).AsDouble();
if (familyInstance.Host is not Level)
{
return;
}
if (!familyInstance.Symbol.IsActive)
{
familyInstance.Symbol.Activate();
}
if (familyInstance.Host is Level hostLevel)
{
var offset = hostLevel.Elevation + originOffset - level.Elevation;
var loc = familyInstance.Location as LocationCurve;
var p1 = loc.Curve.GetEndPoint(0);
var p2 = loc.Curve.GetEndPoint(1);
var line = Line.CreateBound(p1.Add(XYZ.BasisZ * level.Elevation), p2.Add(XYZ.BasisZ * level.Elevation));
var newFamilyInstance = doc.Create.NewFamilyInstance(level.GetPlaneReference(), line, familyInstance.Symbol);
var offsetParam = newFamilyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
offsetParam.Set(offset);
foreach (Parameter param in familyInstance.Parameters)
{
if (param.IsReadOnly || param.Definition.Name == offsetParam.Definition.Name)
{
continue;
}
switch (param.StorageType)
{
case StorageType.None:
break;
case StorageType.Integer:
newFamilyInstance.get_Parameter(param.Definition).Set(param.AsInteger());
break;
case StorageType.Double:
newFamilyInstance.get_Parameter(param.Definition).Set(param.AsDouble());
break;
case StorageType.String:
newFamilyInstance.get_Parameter(param.Definition).Set(param.AsString());
break;
case StorageType.ElementId:
newFamilyInstance.get_Parameter(param.Definition).Set(param.AsElementId());
break;
}
}
}
doc.Delete(familyInstance.Id);
}
/// <summary>
/// 修改基于标高的族
/// </summary>
/// <param name="doc"></param>
/// <param name="level"></param>
/// <param name="familyInstance"></param>
private static void ModifyOneLevelBasedFamily(Document doc, Level level, FamilyInstance familyInstance)
{
var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM);
baseLevelParam.Set(level.Id);
var param = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
if (param == null || param.IsReadOnly)
{
return;
}
var value = param.AsDouble();
var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level;
param.Set(originLevel.Elevation + value - level.Elevation);
}
/// <summary>
/// 修改基于两个标高的族
/// </summary>
/// <param name="doc"></param>
/// <param name="levels"></param>
/// <param name="level"></param>
/// <param name="familyInstance"></param>
private static void ModifyTwoLevelBasedFamily(Document doc, List<Level> levels, Level level, FamilyInstance familyInstance)
{
var n = levels.FindIndex(l => l.Id == level.Id);
var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM);
var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level;
baseLevelParam.Set(level.Id);
var baseOffsetParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM);
var baseOffsetValue = baseOffsetParam.AsDouble();
baseOffsetParam.Set(baseOffsetValue + originLevel.Elevation - level.Elevation);
var topLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM);
originLevel = doc.GetElement(topLevelParam.AsElementId()) as Level;
topLevelParam.Set(levels[n + 1].Id);
var topOffsetParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM);
var topOffsetValue = topOffsetParam.AsDouble();
familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(originLevel.Elevation + topOffsetValue - levels[n + 1].Elevation);
}
/// <summary>
/// 修改基于墙
/// </summary>
/// <param name="view"></param>
/// <param name="levels"></param>
/// <param name="level"></param>
/// <param name="elem"></param>
private static void ModifyWall(View view, List<Level> levels, Level level, Element elem)
{
var wall = (Wall)elem;
var doc = elem.Document;
var isExist = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).Cast<FamilyInstance>().Any(fi => fi.Host?.Id == wall.Id);
if (isExist)
{
return;
}
var n = levels.FindIndex(l => l.Id == level.Id);
var wallBox = wall.get_BoundingBox(view);
var minZ = wallBox.Min.Z;
var maxZ = wallBox.Max.Z;
wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(level.Id);
wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(minZ - level.Elevation);
wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(levels[n + 1].Id);
wall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - levels[n + 1].Elevation);
}
/// <summary>
/// 修改基于工作平面的族
/// </summary>
/// <param name="doc"></param>
/// <param name="level"></param>
/// <param name="familyInstance"></param>
private static void ModifyWorkPlaneBasedFamily(Document doc, Level level, FamilyInstance familyInstance)
{
var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM);
//var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level;
//var hostParam = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_PARAM);
//var hostParamValue = doc.GetElement(hostParam.AsElementId());
if (familyInstance.Host is Level)
{
if (!familyInstance.Symbol.IsActive)
{
familyInstance.Symbol.Activate();
}
var lop = familyInstance.Location as LocationPoint;
var newFamilyInstance = doc.Create.NewFamilyInstance(level.GetPlaneReference(), lop?.Point, familyInstance.HandOrientation, familyInstance.Symbol);
var p = newFamilyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).Definition;
foreach (Parameter param in familyInstance.Parameters)
{
if (param.IsReadOnly || param.Definition.Name == p.Name)
{
continue;
}
switch (param.StorageType)
{
case StorageType.None:
break;
case StorageType.Integer:
newFamilyInstance.get_Parameter(param.Definition).Set(param.AsInteger());
break;
case StorageType.Double:
newFamilyInstance.get_Parameter(param.Definition).Set(param.AsDouble());
break;
case StorageType.String:
newFamilyInstance.get_Parameter(param.Definition).Set(param.AsString());
break;
case StorageType.ElementId:
newFamilyInstance.get_Parameter(param.Definition).Set(param.AsElementId());
break;
}
}
doc.Delete(familyInstance.Id);
}
else
{
if (baseLevelParam.IsReadOnly == false)
{
baseLevelParam.Set(level.Id);
}
}
}
}