403 lines
16 KiB
C#
403 lines
16 KiB
C#
|
|
using Autodesk.Revit.DB;
|
|||
|
|
using Autodesk.Revit.DB.Electrical;
|
|||
|
|
using Autodesk.Revit.DB.Mechanical;
|
|||
|
|
using Autodesk.Revit.DB.Plumbing;
|
|||
|
|
using Autodesk.Revit.UI;
|
|||
|
|
|
|||
|
|
using Sai.RvKits.Windows;
|
|||
|
|
|
|||
|
|
|
|||
|
|
namespace Sai.RvKits.RvFamily;
|
|||
|
|
|
|||
|
|
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(ts =>
|
|||
|
|
{
|
|||
|
|
//对比标高,得到实际分层位置
|
|||
|
|
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);
|
|||
|
|
// WinDialogHelper.ShowAhead(errorResolveWin);
|
|||
|
|
//}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 设置管线
|
|||
|
|
/// </summary>
|
|||
|
|
/// <returns></returns>
|
|||
|
|
public List<MessageModel> SetMEPCurves()
|
|||
|
|
{
|
|||
|
|
List<MessageModel> errors = [];
|
|||
|
|
doc.Invoke(ts =>
|
|||
|
|
{
|
|||
|
|
//对比标高,得到实际分层位置
|
|||
|
|
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);
|
|||
|
|
// WinDialogHelper.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();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var hostLevel = familyInstance.Host as Level;
|
|||
|
|
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);
|
|||
|
|
var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level;
|
|||
|
|
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();
|
|||
|
|
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>
|
|||
|
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
|||
|
|
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;
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
doc.Delete(familyInstance.Id);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (baseLevelParam.IsReadOnly == false)
|
|||
|
|
{
|
|||
|
|
baseLevelParam.Set(level.Id);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|