426 lines
18 KiB
C#
426 lines
18 KiB
C#
|
||
using Autodesk.Revit.DB;
|
||
using Autodesk.Revit.DB.Electrical;
|
||
|
||
using Autodesk.Revit.DB.IFC;
|
||
using Autodesk.Revit.DB.Mechanical;
|
||
using Autodesk.Revit.DB.Plumbing;
|
||
|
||
using System;
|
||
using System.Linq;
|
||
|
||
namespace Szmedi.RvKits.ModelManager
|
||
{
|
||
/// <summary>
|
||
/// 基于标高的
|
||
/// </summary>
|
||
public static class BaseLevelHelpers
|
||
{
|
||
/// <summary>
|
||
/// 获取基于标高的边界
|
||
/// </summary>
|
||
/// <param name="levelList"></param>
|
||
/// <returns></returns>
|
||
public static Dictionary<Level, Outline> GetRegions(List<Level> levelList)
|
||
{
|
||
Dictionary<Level, Outline> outlines = new();
|
||
|
||
////获取标高范围
|
||
for (int i = 0; i < levelList.Count() - 1; i++)
|
||
{
|
||
Level baseLevel = levelList.ElementAt(i);
|
||
Level topLevel = levelList.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);
|
||
outlines.Add(baseLevel, outline);
|
||
}
|
||
|
||
return outlines;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 修改基于线的族
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="level"></param>
|
||
/// <param name="familyInstance"></param>
|
||
public static void ModifyCurveBasedFamily(Level level, FamilyInstance familyInstance)
|
||
{
|
||
var originOffset = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).AsDouble();
|
||
var doc = level.Document;
|
||
|
||
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;
|
||
default:
|
||
throw new ArgumentOutOfRangeException();
|
||
}
|
||
}
|
||
|
||
doc.Delete(familyInstance.Id);
|
||
}
|
||
/// <summary>
|
||
/// 修改基于标高的族
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="level"></param>
|
||
/// <param name="familyInstance"></param>
|
||
public static void ModifyOneLevelBasedFamily(Level level, FamilyInstance familyInstance)
|
||
{
|
||
var doc = level.Document;
|
||
var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM);
|
||
var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level;
|
||
if (!baseLevelParam.IsReadOnly && baseLevelParam.UserModifiable)
|
||
{
|
||
baseLevelParam.Set(level.Id);
|
||
var param = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM);
|
||
if (param != null && param.IsReadOnly == false)
|
||
{
|
||
var value = param.AsDouble();
|
||
param.Set(originLevel.Elevation + value - level.Elevation);
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 修改基于两个标高的族
|
||
/// </summary>
|
||
/// <param name="levels"></param>
|
||
/// <param name="level"></param>
|
||
/// <param name="familyInstance"></param>
|
||
public static void ModifyTwoLevelBasedFamily(List<Level> levels, Level level, FamilyInstance familyInstance)
|
||
{
|
||
var levelOrdered = levels.OrderBy(l => l.Elevation).ToList();
|
||
var n = levelOrdered.FindIndex(l => l.Id == level.Id);
|
||
var doc = level.Document;
|
||
|
||
var baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM);
|
||
var originLevel = doc.GetElement(baseLevelParam.AsElementId()) as Level;
|
||
if (!baseLevelParam.IsReadOnly && baseLevelParam.UserModifiable)
|
||
{
|
||
baseLevelParam.Set(level.Id);
|
||
|
||
var baseOffestParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM);
|
||
|
||
var baseOffestValue = baseOffestParam.AsDouble();
|
||
baseOffestParam.Set(baseOffestValue + originLevel.Elevation - level.Elevation);
|
||
|
||
if (n + 1 < levelOrdered.Count)
|
||
{
|
||
var topLevelParam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM);
|
||
originLevel = doc.GetElement(topLevelParam.AsElementId()) as Level;
|
||
topLevelParam.Set(levelOrdered[n + 1].Id);
|
||
var topOffestparam = familyInstance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM);
|
||
|
||
var topffestValue = topOffestparam.AsDouble();
|
||
familyInstance
|
||
.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM)
|
||
.Set(originLevel.Elevation + topffestValue - levelOrdered[n + 1].Elevation);
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 修改墙标高
|
||
/// </summary>
|
||
/// <param name="view"></param>
|
||
/// <param name="levels">项目中的所有标高</param>
|
||
/// <param name="level"></param>
|
||
/// <param name="wall"></param>
|
||
public static void ModifyWall(View view, List<Level> levels, Level level, Wall wall)
|
||
{
|
||
var doc = wall.Document;
|
||
var isExist = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(FamilyInstance))
|
||
.Cast<FamilyInstance>()
|
||
.Any(fi => fi.Host?.Id == wall.Id);
|
||
var instances = doc.OfType<FamilyInstance>().Where(ins => ins.Host != null && ins.Host.Id == wall.Id);
|
||
//存在主体依赖
|
||
if (isExist)
|
||
{
|
||
return;
|
||
}
|
||
var levelOrdered = levels.OrderBy(l => l.Elevation).ToList();
|
||
var n = levelOrdered.FindIndex(l => l.Id == level.Id);
|
||
var wallBox = wall.get_BoundingBox(view);
|
||
var minZ = wallBox.Min.Z;
|
||
var maxZ = wallBox.Max.Z;
|
||
if (ExporterIFCUtils.HasElevationProfile(wall) || instances.Any())
|
||
{
|
||
return;
|
||
}
|
||
|
||
wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(level.Id);
|
||
var originBaseOffest = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(minZ - level.Elevation);
|
||
|
||
if (n + 1 < levelOrdered.Count)
|
||
{
|
||
wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(levelOrdered[n + 1].Id);
|
||
var originTopOffest = wall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(maxZ - levelOrdered[n + 1].Elevation);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 修改基于工作平面的族
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="level"></param>
|
||
/// <param name="familyInstance"></param>
|
||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||
public static void ModifyWorkPlaneBasedFamily(Level level, FamilyInstance familyInstance)
|
||
{
|
||
Parameter baseLevelParam = familyInstance.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM);
|
||
var doc = level.Document;
|
||
//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();
|
||
}
|
||
|
||
LocationPoint lop = familyInstance.Location as LocationPoint;
|
||
FamilyInstance newFamilyInstance = doc.Create.NewFamilyInstance(level.GetPlaneReference(), lop?.Point, familyInstance.HandOrientation, familyInstance.Symbol);
|
||
Definition 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:
|
||
throw new ArgumentOutOfRangeException();
|
||
}
|
||
}
|
||
|
||
doc.Delete(familyInstance.Id);
|
||
}
|
||
else
|
||
{
|
||
if (baseLevelParam.IsReadOnly == false)
|
||
{
|
||
baseLevelParam.Set(level.Id);
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 设置族实例
|
||
/// </summary>
|
||
/// <param name="levelOutlines">标高范围,通过GetRegion方法获得</param>
|
||
/// <returns></returns>
|
||
public static List<MessageModel> SetInstances(List<Level> levels)
|
||
{
|
||
var levelOutlines = GetRegions(levels);
|
||
List<MessageModel> errors = new();
|
||
var doc = levels.FirstOrDefault().Document;
|
||
|
||
doc.Invoke(ts =>
|
||
{
|
||
//对比标高,得到实际分层位置
|
||
foreach (KeyValuePair<Level, Outline> keyPair in levelOutlines)
|
||
{
|
||
//得到在标高范围内的元素
|
||
BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value);
|
||
Level level = keyPair.Key;
|
||
List<Element> insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem is FamilyInstance && (elem.LevelId != level.Id || elem.get_BoundingBox(doc.ActiveView) != null)).ToList();
|
||
|
||
foreach (Element elem in insideCollector)
|
||
{
|
||
try
|
||
{
|
||
//获取构件定位方式,基于标高,基于主体(基于面,基于线,基于主体构件:墙板等),基于点
|
||
if (elem is not FamilyInstance familyInstance)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
FamilyPlacementType placementType = familyInstance.Symbol.Family.FamilyPlacementType;
|
||
|
||
switch (placementType)
|
||
{
|
||
case FamilyPlacementType.OneLevelBased:
|
||
ModifyOneLevelBasedFamily(level, familyInstance);
|
||
break;
|
||
case FamilyPlacementType.OneLevelBasedHosted:
|
||
break;
|
||
case FamilyPlacementType.TwoLevelsBased:
|
||
ModifyTwoLevelBasedFamily(levels, level, familyInstance);
|
||
break;
|
||
case FamilyPlacementType.ViewBased:
|
||
break;
|
||
case FamilyPlacementType.WorkPlaneBased:
|
||
ModifyWorkPlaneBasedFamily(level, familyInstance);
|
||
break;
|
||
case FamilyPlacementType.CurveBased:
|
||
ModifyCurveBasedFamily(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(uidoc, errors);
|
||
// var errorResolveWin = new ErrorResolveWin(processorViewModel);
|
||
// WinDialogAssists.ShowAhead(errorResolveWin);
|
||
//}
|
||
}
|
||
/// <summary>
|
||
/// 设置管线
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public static List<MessageModel> SetMEPCurves(List<Level> levels)
|
||
{
|
||
List<MessageModel> errors = new();
|
||
|
||
var doc = levels.FirstOrDefault().Document;
|
||
var levelOutlines = GetRegions(levels);
|
||
doc.Invoke(ts =>
|
||
{
|
||
//对比标高,得到实际分层位置
|
||
foreach (KeyValuePair<Level, Outline> keyPair in levelOutlines)
|
||
{
|
||
//得到在标高范围内的元素
|
||
BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value);
|
||
Level level = keyPair.Key;
|
||
List<Element> insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem.LevelId != level.Id || elem.get_BoundingBox(doc.ActiveView) != null).ToList();
|
||
|
||
foreach (Element 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 static List<MessageModel> SetWalls(List<Level> levels)
|
||
{
|
||
List<MessageModel> errors = new();
|
||
var doc = levels.FirstOrDefault().Document;
|
||
|
||
var levelOutlines = GetRegions(levels);
|
||
doc.Invoke(_ =>
|
||
{
|
||
//对比标高,得到实际分层位置
|
||
foreach (KeyValuePair<Level, Outline> keyPair in levelOutlines)
|
||
{
|
||
//得到在标高范围内的元素
|
||
BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value);
|
||
Level level = keyPair.Key;
|
||
List<Element> insideCollector = new FilteredElementCollector(doc).WherePasses(insideFilter).Where(elem => elem.LevelId != level.Id || elem.get_BoundingBox(doc.ActiveView) != null).ToList();
|
||
foreach (Element elem in insideCollector)
|
||
{
|
||
try
|
||
{
|
||
if (elem is Wall wall)
|
||
{
|
||
ModifyWall(doc.ActiveView, levels, level, wall);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
errors.Add(new MessageModel(elem, ex.Message));
|
||
}
|
||
}
|
||
}
|
||
}, "校正墙体标高");
|
||
return errors;
|
||
//if (errors.Any())
|
||
//{
|
||
// var processorViewModel = new ErrorResolveViewModel(uidoc, errors);
|
||
// var errorResolveWin = new ErrorResolveWin(processorViewModel);
|
||
// WinDialogAssists.ShowAhead(errorResolveWin);
|
||
//}
|
||
}
|
||
}
|
||
} |