Files
ShrlAlgoToolkit/ShrlAlgoToolkit.RevitCore/Extensions/DocumentExtensions.cs
2026-02-21 16:31:24 +08:00

1351 lines
44 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB.Visual;
using ShrlAlgoToolkit.RevitCore.Assists;
namespace ShrlAlgoToolkit.RevitCore.Extensions;
public static class DocumentExtensions
{
/// <summary>
/// 轴网标注
/// </summary>
/// <param name="doc"></param>
/// <param name="chainDimensionLine"></param>
/// <param name="extremeWallVariant"></param>
/// <param name="grids"></param>
/// <returns></returns>
public static Dimension CreateDimensionByExtremeGrids(
this Document doc,
Line chainDimensionLine,
ExtremeWallVariant extremeWallVariant,
List<Grid> grids
)
{
Dimension result;
if (!grids.Any())
{
result = null;
}
else
{
Dimension dimension = null;
ReferenceArray referenceArray = new();
if (extremeWallVariant is ExtremeWallVariant.Left or ExtremeWallVariant.Right)
{
var list = (
from g in grids
where ((Line)g.Curve).Direction.DotProduct(XYZ.BasisY) < 0.0001
select g
).ToList();
if (list.Any())
{
list.Sort((g1, g2) => g1.Curve.GetEndPoint(0).Y.CompareTo(g2.Curve.GetEndPoint(0).Y));
List<Grid> list2 = [list.First(), list.Last()];
foreach (var grid in list2)
{
referenceArray.Append(new Reference(grid));
}
}
}
else
{
var list3 = (
from g in grids
where ((Line)g.Curve).Direction.DotProduct(XYZ.BasisX) < 0.0001
select g
).ToList();
if (list3.Any())
{
list3.Sort((g1, g2) => g1.Curve.GetEndPoint(0).X.CompareTo(g2.Curve.GetEndPoint(0).X));
List<Grid> list4 = [list3.First(), list3.Last()];
foreach (var grid2 in list4)
{
referenceArray.Append(new Reference(grid2));
}
}
}
if (!referenceArray.IsEmpty && referenceArray.Size > 1)
{
dimension = doc.Create.NewDimension(doc.ActiveView, chainDimensionLine, referenceArray);
}
result = dimension;
}
return result;
}
/// <summary>
/// 获取所有可预览视图ID
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="doc"></param>
/// <param name="setting"></param>
/// <returns></returns>
public static ElementId FindPreviewId<T>(this Document doc, DocumentPreviewSettings setting) where T : View
{
var collector = new FilteredElementCollector(doc).OfClass(typeof(T));
if (!collector.Any())
{
return new FilteredElementCollector(doc).OfClass(typeof(ViewPlan)).FirstElementId();
}
var viewForPreview = collector.OfType<T>().First(v => setting.IsViewIdValidForPreview(v.Id));
return viewForPreview.Id;
}
/// <summary>
/// 获取标高范围框
/// </summary>
/// <remarks>最低标高除了包含以上部分,还包含以下部分,最高标高包含以上部分</remarks>
/// <param name="doc"></param>
/// <returns></returns>
public static Dictionary<Level, Outline> GetLevelRanges(this Document doc)
{
var levels = doc.OfClass<Level>().Cast<Level>().OrderBy(l => l.Elevation).ToList();
Dictionary<Level, Outline> levelOutlines = [];
//获取标高范围
for (var i = 0; i < levels.Count; i++)
{
var baseLevel = levels[i];
XYZ min = new(double.MinValue, double.MinValue, baseLevel.Elevation);
XYZ max;
Outline outline;
if (i == 0)
{
min = new XYZ(double.MinValue, double.MinValue, double.MinValue);
var topLevel = levels[i + 1];
max = new XYZ(double.MaxValue, double.MaxValue, topLevel.Elevation);
outline = new Outline(min, max);
}
else if (i < levels.Count - 1)
{
var topLevel = levels[i + 1];
max = new XYZ(double.MaxValue, double.MaxValue, topLevel.Elevation);
outline = new Outline(min, max);
}
else//最后一个标高以上
{
max = new XYZ(double.MaxValue, double.MaxValue, double.MaxValue);
outline = new Outline(min, max);
}
levelOutlines.Add(baseLevel, outline);
}
return levelOutlines;
}
public static Dimension CreateDimensionByOverallWalls(
this Document doc,
Line chainDimensionLine,
IReadOnlyCollection<Wall> sideWalls,
ExtremeWallVariant extremeWallVariant
)
{
Dimension dimension = null;
var list = sideWalls.Where(w => w.Orientation.DotProduct(XYZ.BasisX) < 0.0001).ToList();
var list2 = sideWalls.Where(w => w.Orientation.DotProduct(XYZ.BasisY) < 0.0001).ToList();
Dimension result;
if (!list.Any() && !list2.Any())
{
result = null;
}
else
{
ReferenceArray referenceArray = new();
if (extremeWallVariant is ExtremeWallVariant.Right or ExtremeWallVariant.Left)
{
List<PlanarFace> list3 = [];
foreach (var wall in list)
{
foreach (var planarFace in wall.GetFaces())
{
if (planarFace.IsHorizontal())
{
list3.Add(planarFace);
}
}
var elementArray = ((LocationCurve)wall.Location).get_ElementsAtJoin(0);
var elementArray2 = ((LocationCurve)wall.Location).get_ElementsAtJoin(1);
List<Wall> list4 = [];
foreach (Element element in elementArray)
{
var wallFromListById = (from w in list where w.Id == element.Id select w).First();
if (wallFromListById != null)
{
list4.Add(wallFromListById);
}
}
foreach (Element element2 in elementArray2)
{
var wallFromListById2 = (from w in list where w.Id == element2.Id select w).First();
if (wallFromListById2 != null)
{
list4.Add(wallFromListById2);
}
}
foreach (var wall2 in list4)
{
foreach (var planarFace2 in wall2.GetFaces())
{
if (planarFace2.IsHorizontal())
{
list3.Add(planarFace2);
}
}
}
}
list3.Sort((f1, f2) => f1.GetMinY().CompareTo(f2.GetMinY()));
referenceArray.Append(list3.First().Reference);
referenceArray.Append(list3.Last().Reference);
}
if (extremeWallVariant is ExtremeWallVariant.Top or ExtremeWallVariant.Bottom)
{
List<PlanarFace> list5 = [];
foreach (var wall3 in list2)
{
foreach (var planarFace3 in wall3.GetFaces())
{
if (planarFace3.IsVertical())
{
list5.Add(planarFace3);
}
}
var elementArray3 = ((LocationCurve)wall3.Location).get_ElementsAtJoin(0);
var elementArray4 = ((LocationCurve)wall3.Location).get_ElementsAtJoin(1);
List<Wall> list6 = [];
foreach (Element element3 in elementArray3)
{
var wallFromListById3 = (from w in list where w.Id == element3.Id select w).First();
if (wallFromListById3 != null)
{
list6.Add(wallFromListById3);
}
}
foreach (Element element4 in elementArray4)
{
var wallFromListById4 = (from w in list where w.Id == element4.Id select w).First();
if (wallFromListById4 != null)
{
list6.Add(wallFromListById4);
}
}
foreach (var wall4 in list6)
{
foreach (var planarFace4 in wall4.GetFaces())
{
var isVertical2 = planarFace4.IsVertical();
if (isVertical2)
{
list5.Add(planarFace4);
}
}
}
}
list5.Sort((f1, f2) => f1.GetMinX().CompareTo(f2.GetMinX()));
referenceArray.Append(list5[0].Reference);
referenceArray.Append(list5.Last().Reference);
}
if (!referenceArray.IsEmpty)
{
doc.Invoke(_ =>
{
dimension = doc.Create.NewDimension(doc.ActiveView, chainDimensionLine, referenceArray);
});
}
result = dimension;
}
return result;
}
/// <summary>
/// 创建房间
/// </summary>
/// <param name="doc"></param>
/// <param name="level"></param>
/// <param name="phase"></param>
public static void CreateRoom(this Document doc, Level level, Phase phase)
{
// 获取基于标高level的一个视图
var defaultView = new FilteredElementCollector(doc)
.OfClass(typeof(View))
.Cast<View>()
.FirstOrDefault(v => v.GenLevel != null && v.GenLevel.Id == level.Id);
// 确保视图不为空
if (defaultView != null)
{
var defaultPhase = defaultView.get_Parameter(BuiltInParameter.VIEW_PHASE);
if (defaultPhase != null && defaultPhase.AsElementId() == phase.Id)
{
var circuits = doc.get_PlanTopology(level, phase).Circuits;
foreach (PlanCircuit planCircuit in circuits)
{
doc.Create.NewRoom(null, planCircuit);
}
}
}
}
/// <summary>
/// 创建表格
/// </summary>
/// <param name="doc"></param>
/// <param name="legend"></param>
/// <param name="rowCount"></param>
/// <param name="columnCount"></param>
/// <param name="gridWidth"></param>
/// <param name="gridHeight"></param>
public static void CreateTable(
this Document doc,
View legend,
int rowCount,
int columnCount,
double gridWidth,
double gridHeight
)
{
CurveArray curveArray = new();
for (var i = 0; i <= rowCount; i++) //水平网格
{
var l = Line.CreateBound(XYZ.Zero, XYZ.BasisX * gridWidth * columnCount)
.CreateOffset(gridHeight * i, -XYZ.BasisZ);
curveArray.Append(l);
}
Curve line = Line.CreateBound(XYZ.Zero, XYZ.BasisY * rowCount * gridHeight);
curveArray.Append(line);
for (var i = 0; i <= columnCount; i++) //垂直网格
{
line = line.CreateOffset(gridWidth, XYZ.BasisZ);
curveArray.Append(line);
}
doc.Create.NewDetailCurveArray(legend, curveArray);
}
/// <summary>
/// 创建表格
/// </summary>
/// <param name="doc"></param>
/// <param name="legend">图例视图</param>
/// <param name="rowCount">行数</param>
/// <param name="columnCount">列数</param>
/// <param name="gridHeight">单元格高度</param>
/// <param name="gridWidths">各列对应的宽度</param>
public static void CreateTable(
this Document doc,
View legend,
int rowCount,
int columnCount,
double gridHeight,
params double[] gridWidths
)
{
if (columnCount != gridWidths.Length)
{
return;
}
CurveArray curveArray = new();
var totalWidth = 0.0;
foreach (var w in gridWidths)
{
totalWidth += w;
}
for (var i = 0; i <= rowCount; i++) //水平网格
{
var c = Line.CreateBound(XYZ.Zero, XYZ.BasisX * totalWidth).CreateOffset(gridHeight * i, -XYZ.BasisZ);
curveArray.Append(c);
}
Curve line = Line.CreateBound(XYZ.Zero, XYZ.BasisY * rowCount * gridHeight);
curveArray.Append(line);
for (var i = 0; i < columnCount; i++) //垂直网格
{
line = line.CreateOffset(gridWidths[i], XYZ.BasisZ);
curveArray.Append(line);
}
doc.Create.NewDetailCurveArray(legend, curveArray);
}
/// <summary>
/// 创建表格
/// </summary>
/// <param name="legend">图例视图</param>
/// <param name="rowCount">行数(含标题行)</param>
/// <param name="columnCount">列数</param>
/// <param name="headHeight"></param>
/// <param name="gridHeight">单元格高度</param>
/// <param name="gridWidths">各单元格对应的宽度</param>
public static void CreateTable(
View legend,
int rowCount,
int columnCount,
double headHeight,
double gridHeight,
params double[] gridWidths
)
{
var doc = legend.Document;
if (columnCount != gridWidths.Length)
{
MessageBox.Show("列数和提供的列宽数量不一致。", "提示");
return;
}
CurveArray curveArray = new();
var totalWidth = 0.0;
foreach (var w in gridWidths)
{
totalWidth += w;
}
for (var i = 0; i <= rowCount - 1; i++) //水平网格
{
var c = Line.CreateBound(XYZ.Zero, XYZ.BasisX * totalWidth).CreateOffset(gridHeight * i, -XYZ.BasisZ);
curveArray.Append(c);
}
//标题行
var line = Line.CreateBound(XYZ.Zero, XYZ.BasisX * totalWidth)
.CreateOffset((gridHeight * (rowCount - 1)) + headHeight, -XYZ.BasisZ);
curveArray.Append(line);
//列
line = Line.CreateBound(XYZ.Zero, XYZ.BasisY * (((rowCount - 1) * gridHeight) + headHeight));
curveArray.Append(line);
for (var i = 0; i < columnCount; i++) //垂直网格
{
line = line.CreateOffset(gridWidths[i], XYZ.BasisZ);
curveArray.Append(line);
}
doc.Create.NewDetailCurveArray(legend, curveArray);
}
public static void CreateTag(this Document doc, List<Reference> references, TagMode tagMode, bool hasLeader)
{
foreach (var refer in references)
{
try
{
IndependentTag.Create(
doc,
doc.ActiveView.Id,
refer,
hasLeader,
tagMode,
TagOrientation.Horizontal,
new XYZ(0, 0, 0)
);
}
catch
{
// ignored
}
}
}
public static void DeleteFamilyType(this Document famdoc)
{
// 得到FamilyManager
var familyMgr = famdoc.FamilyManager;
if (familyMgr.CurrentType != null)
{
// 只有当前族类型存在,我们才能调用下面的删除方法
familyMgr.DeleteCurrentType();
// 一般来说,当删除结束后,第一个族类型会成为当前类型,
// 但是为了确保安全, 建议你显式设置成你需要的类型
if (familyMgr.Types.Size != 0)
{
var type = familyMgr.Types.Cast<FamilyType>().ElementAt(0);
familyMgr.CurrentType = type;
}
}
}
/// <summary>
/// 删除定位点重合的族实例
/// </summary>
/// <param name="doc"></param>
/// <param name="cardInstances"></param>
public static void DeleteOverlapInstance(this Document doc, List<FamilyInstance> cardInstances)
{
List<ElementId> idsToDelete = [];
foreach (var ins in cardInstances)
{
var lp = ins.GetLocXYZ();
foreach (var card in cardInstances)
{
var lpt = card.GetLocXYZ();
if (!card.Id.Equals(ins.Id) && lp.IsAlmostEqualTo(lpt))
{
idsToDelete.Add(ins.Id);
idsToDelete.Add(card.Id);
break;
}
}
}
doc.Delete(idsToDelete);
}
/// <summary>
/// 复制图例
/// </summary>
/// <param name="doc"></param>
/// <param name="legendName"></param>
/// <param name="viewScale">比例</param>
/// <returns></returns>
public static View DuplicateLegend(Document doc, string legendName, int viewScale)
{
var legends = doc.OfClass<View>()
.OfCategory(BuiltInCategory.OST_Views)
.Cast<View>()
.Where(v => v.ViewType == ViewType.Legend)
.ToList();
if (!legends.Any())
{
MessageBox.Show("当前项目中没有图例", "温馨提示");
return null;
}
var legendToCopy = legends.FirstOrDefault();
var newLegendId = legendToCopy?.Duplicate(ViewDuplicateOption.Duplicate);
var newLegend = doc.GetElement(newLegendId) as View;
for (var i = 0; i < 100; i++)
{
try
{
newLegend!.Name = $"{legendName} {i}";
break;
}
catch (Autodesk.Revit.Exceptions.ArgumentException) { }
}
newLegend!.Scale = viewScale;
return newLegend;
}
/// <summary>
/// 翻转工作平面
/// </summary>
/// <param name="doc"></param>
/// <param name="id"></param>
public static void FlipWorkPlane(this Document doc, ElementId id)
{
var fi = (FamilyInstance)doc.GetElement(id);
if (fi != null)
{
fi.IsWorkPlaneFlipped = !fi.IsWorkPlaneFlipped;
}
}
public static FamilySymbol GetAndActiveDefaultFamilySymbol(this Document doc, string rfaFile)
{
var family = GetOrLoadedFamily(doc, rfaFile);
FamilySymbol symbol = null;
if (family != null)
{
var symbolId = family.GetFamilySymbolIds().FirstOrDefault();
symbol = doc.GetElement(symbolId) as FamilySymbol;
Debug.Assert(symbol != null, nameof(symbol) + " != null");
if (!symbol.IsActive)
{
symbol.Activate();
}
}
return symbol;
}
/// <summary>
/// 获取族中的元素
/// </summary>
/// <param name="famdoc"></param>
/// <returns></returns>
public static List<ElementId> GetFamilySolidForm(this Document famdoc)
{
var ids = new List<ElementId>();
if (famdoc.IsFamilyDocument)
{
var solids = new FilteredElementCollector(famdoc)
.OfClass(typeof(GenericForm))
.Cast<GenericForm>()
.Where(x => x.IsSolid)
.Select(y => y.Id);
var fiids = new FilteredElementCollector(famdoc).OfClass(typeof(FamilyInstance)).Select(y => y.Id);
ids.AddRange(solids);
ids.AddRange(fiids);
}
return ids;
}
/// <summary>
/// 填充样式
/// </summary>
/// <param name="doc"></param>
/// <param name="patternName"></param>
/// <returns></returns>
public static ElementId GetFillPatternElemId(this Document doc, string patternName)
{
var fillPatternElemId = ElementId.InvalidElementId;
var fecOfFpe = new FilteredElementCollector(doc).OfClass(typeof(FillPatternElement));
foreach (var element in fecOfFpe.ToElements())
{
var fpe = element as FillPatternElement;
var fp = fpe.GetFillPattern();
if (null != fp && fp.Name == patternName)
{
fillPatternElemId = fpe.Id;
break;
}
}
return fillPatternElemId;
}
/// <summary>
/// 获取已载入同名族,若无,则载入
/// </summary>
/// <param name="doc"></param>
/// <param name="familyPath"></param>
/// <returns></returns>
public static Family GetOrLoadedFamily(this Document doc, string familyPath)
{
var family = new FilteredElementCollector(doc)
.OfClass(typeof(Family))
.Cast<Family>()
.FirstOrDefault(f => f.Name == Path.GetFileNameWithoutExtension(familyPath));
if (family == null && File.Exists(familyPath))
{
doc.LoadFamily(familyPath, new DefaultFamilyLoadOptions(), out family);
}
return family;
}
/// <summary>
/// 获取或创建文字类型
/// </summary>
/// <param name="doc"></param>
/// <param name="textSymbolName">文字类型名称</param>
/// <param name="fontFamily"></param>
/// <param name="fontSize"></param>
/// <param name="widthScale"></param>
/// <returns></returns>
public static TextNoteType GetOrNewTextNoteType(
this Document doc,
string textSymbolName,
string fontFamily,
string fontSize,
string widthScale
)
{
var textNoteType = new FilteredElementCollector(doc)
.OfClass(typeof(TextNoteType))
.OfType<TextNoteType>()
.FirstOrDefault(x => x.Name.Contains(textSymbolName));
if (textNoteType != null)
{
return textNoteType;
}
textNoteType =
new FilteredElementCollector(doc)
.OfClass(typeof(TextNoteType))
.Cast<TextNoteType>()
.FirstOrDefault()
?.Duplicate(textSymbolName) as TextNoteType;
if (textNoteType != null)
{
textNoteType.get_Parameter(BuiltInParameter.TEXT_FONT).SetValueString(fontFamily);
textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).SetValueString(fontSize);
textNoteType.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).SetValueString(widthScale);
}
return textNoteType;
}
/// <summary>
/// 射线法获取参照
/// </summary>
/// <param name="doc"></param>
/// <param name="vector"></param>
public static Reference GetSpotDimensionReference(this Document doc, XYZ vector)
{
Reference reference = null;
if (doc.ActiveView is ViewPlan view)
{
//可能存在贯穿标高的构件,需修改射线贯穿距离
#region
var range = view.GetViewRange();
var bottomLevel = doc.GetElement(range.GetLevelId(PlanViewPlane.BottomClipPlane)) as Level;
var b = range.GetOffset(PlanViewPlane.BottomClipPlane);
var topLevel = doc.GetElement(range.GetLevelId(PlanViewPlane.TopClipPlane)) as Level;
var t = range.GetOffset(PlanViewPlane.TopClipPlane);
var bot = bottomLevel.Elevation + b;
var tt = topLevel.Elevation + t;
var p1 = new XYZ(vector.X, vector.Y, bot);
var p2 = new XYZ(vector.X, vector.Y, tt);
#endregion
var v3d = new FilteredElementCollector(doc)
.OfClass(typeof(View3D))
.Cast<View3D>()
.FirstOrDefault(v => !v.IsTemplate);
//射线法找到相交的元素
ReferenceIntersector intersector = new(v3d);
var refer = intersector.FindNearest(p1, XYZ.BasisZ)?.GetReference();
var refer1 = intersector.FindNearest(p2, -XYZ.BasisZ)?.GetReference();
if (refer != null && refer1 != null)
{
reference = refer.GlobalPoint.Z > refer1.GlobalPoint.Z ? refer : refer1;
}
}
return reference;
//Line l2 = Line.CreateUnbound(vector, XYZ.BasisZ);
}
/// <summary>
/// dwg图层隐藏
/// </summary>
/// <param name="doc"></param>
/// <param name="reference">选择的dwg引用PointOnElement</param>
/// <param name="graphicStyleId"></param>
/// <param name="geoElem"></param>
public static void HideDwgLayer(
this Document doc,
Reference reference,
out ElementId graphicStyleId,
out GeometryElement geoElem
)
{
var dwg = doc.GetElement(reference) as ImportInstance;
graphicStyleId = null;
Options opts =
new()
{
ComputeReferences = true,
IncludeNonVisibleObjects = true,
DetailLevel = 0
};
geoElem = dwg?.get_Geometry(opts);
var geoObj = dwg?.GetGeometryObjectFromReference(reference);
if (
geoObj != null
&& geoObj.GraphicsStyleId != ElementId.InvalidElementId
&& doc.GetElement(geoObj.GraphicsStyleId) is GraphicsStyle gsSelected
)
{
//图层Id
graphicStyleId = gsSelected.GraphicsStyleCategory.Id;
doc.Invoke(
_ =>
{
doc.ActiveView.SetCategoryHidden(gsSelected.GraphicsStyleCategory.Id, true);
},
"隐藏图层"
);
}
}
/// <summary>
/// 链接cad
/// </summary>
/// <param name="doc"></param>
/// <param name="linkPaths"></param>
public static void LinkDwgByPaths(this Document doc, params string[] linkPaths)
{
if (doc is null)
{
throw new ArgumentNullException(nameof(doc));
}
if (linkPaths is null)
{
throw new ArgumentNullException(nameof(linkPaths));
}
var options = new DWGImportOptions { OrientToView = true };
//var li = linkPaths.ToList();
//li.ForEach(famdoc.Link(linkPath, options, famdoc.ActiveView, out _));
foreach (var linkPath in linkPaths)
{
doc.Link(linkPath, options, doc.ActiveView, out _);
}
}
/// <summary>
/// 链接Revit
/// </summary>
/// <param name="doc"></param>
/// <param name="linkPaths"></param>
/// <returns></returns>
public static void LinkRvt(this Document doc, params string[] linkPaths)
{
if (doc is null)
{
throw new ArgumentNullException(nameof(doc));
}
if (linkPaths is null)
{
throw new ArgumentNullException(nameof(linkPaths));
}
foreach (var linkPath in linkPaths)
{
var filePath = new FilePath(linkPath);
var linkOption = new RevitLinkOptions(false);
var result = RevitLinkType.Create(doc, filePath, linkOption);
var instance = RevitLinkInstance.Create(doc, result.ElementId);
if (doc.GetElement(instance.GetTypeId()) is not RevitLinkType type)
{
return;
}
type.AttachmentType = AttachmentType.Attachment;
type.PathType = PathType.Relative;
}
}
public static void ReadImporterFile(
this Document revitDoc,
ShapeImporterSourceFormat sourceFormat,
BuiltInCategory builtInCategory
)
{
//ofd.Filter = "SAT Files (.sat)|.sat";
FileOpenDialog ofd = new("*");
if (ofd.Show() == ItemSelectionDialogResult.Confirmed)
{
ShapeImporter shapeImporter = new() { InputFormat = sourceFormat };
var mp = ofd.GetSelectedModelPath();
var fileName = ModelPathUtils.ConvertModelPathToUserVisiblePath(mp);
var shapes = shapeImporter.Convert(revitDoc, fileName);
if (shapes.Count != 0)
{
using Transaction tr = new(revitDoc, "创建内建模型");
tr.Start();
var dsImportedSat = DirectShape.CreateElement(revitDoc, new ElementId(builtInCategory));
dsImportedSat.SetShape(shapes);
tr.Commit();
}
}
}
/// <summary>
/// 有类型定义的DirectShape
/// </summary>
/// <param name="doc"></param>
/// <param name="definitionId">定义名称,即是族名称、类型名称(强制一致),创建多个实例时,如果相同,则会合并在一个族中</param>
/// <param name="category">族类别</param>
/// <param name="geos">几何</param>
/// <returns></returns>
public static DirectShape CreateDirectShapeInstance(this Document doc, string definitionId, BuiltInCategory category, List<GeometryObject> geos)
{
DirectShapeLibrary directShapeLibrary = DirectShapeLibrary.GetDirectShapeLibrary(doc);
ElementId directShapeTypeId = directShapeLibrary.FindDefinitionType(definitionId);
if (doc.GetElement(directShapeTypeId) == null)
{
var directShapeType = DirectShapeType.Create(doc, definitionId, new ElementId(category));
directShapeTypeId = directShapeType.Id;
directShapeLibrary.AddDefinitionType(definitionId, directShapeTypeId);
}
//else
//{
// directShapeLibrary.AddDefinition(definitionId, geos);
//}
var shape = DirectShape.CreateElementInstance(doc, directShapeTypeId, new ElementId(category), definitionId, Transform.Identity);
//shape.SetTypeId(directShapeTypeId);
//shape.SetName();实例名称
shape.SetShape(geos);
return shape;
}
/// <summary>
/// 无名称定义的DirectShape
/// </summary>
/// <param name="doc"></param>
/// <param name="geos"></param>
/// <param name="category"></param>
/// <returns></returns>
public static DirectShape CreateDirectShape(this Document doc, List<GeometryObject> geos, BuiltInCategory category)
{
var shape = DirectShape.CreateElement(doc, new ElementId(category));
shape.SetShape(geos);
return shape;
}
/// <summary>
/// 删除Revit链接
/// </summary>
/// <param name="doc"></param>
/// <param name="linkPaths"></param>
/// <returns></returns>
public static void RemoveLinks(this Document doc, params string[] linkPaths)
{
if (doc is null)
{
throw new ArgumentNullException(nameof(doc));
}
if (linkPaths is null)
{
throw new ArgumentNullException(nameof(linkPaths));
}
foreach (var linkPath in linkPaths)
{
var links = new FilteredElementCollector(doc).OfClass(typeof(RevitLinkInstance));
foreach (var link in links)
{
if (link.Name.Split(':').Length != 3)
{
continue;
}
if (link is not RevitLinkInstance instance)
{
continue;
}
if (link.Name == Path.GetFileName(linkPath))
{
var type = doc.GetElement(instance.GetTypeId()) as RevitLinkType;
type?.Unload(null);
doc.Invoke(_ =>
{
doc.Delete(instance.Id);
});
}
}
}
}
public static void RenameFamilyType(this Document famdoc, string oldTypeName, string newTypeName)
{
if (famdoc.IsFamilyDocument)
{
// 得到FamilyManager
var familyMgr = famdoc.FamilyManager;
// 族类型的名字,保证在所有族类型中唯一
var isExist = false;
foreach (FamilyType t in familyMgr.Types)
{
if (t.Name == oldTypeName)
{
familyMgr.CurrentType = t;
familyMgr.RenameCurrentType(newTypeName);
isExist = true;
}
}
if (!isExist)
{
familyMgr.NewType(newTypeName);
}
}
else
{
var familySymbol = new FilteredElementCollector(famdoc)
.WhereElementIsElementType()
.FirstOrDefault(t => t.Name == oldTypeName);
if (familySymbol != null)
{
familySymbol.Name = newTypeName;
}
}
}
/// <summary>
/// 设置中心文件
/// </summary>
/// <param name="doc"></param>
/// <param name="centralPath"></param>
/// <returns></returns>
public static void SetCentralFile(this Document doc, string centralPath)
{
if (doc is null)
{
throw new ArgumentNullException(nameof(doc));
}
if (centralPath is null)
{
throw new ArgumentNullException(nameof(centralPath));
}
var saveOption = new SaveAsOptions { OverwriteExistingFile = true };
var sharingOption = new WorksharingSaveAsOptions
{
SaveAsCentral = true,
OpenWorksetsDefault = SimpleWorksetConfiguration.LastViewed
};
saveOption.SetWorksharingOptions(sharingOption);
doc.SaveAs(centralPath, saveOption);
}
/// <summary>
/// 设置Revit链接集合
/// </summary>
/// <param name="centralPath"></param>
/// <param name="linkPaths"></param>
public static void SetLinkList(string centralPath, List<string> linkPaths)
{
if (centralPath is null)
{
throw new ArgumentNullException(nameof(centralPath));
}
if (linkPaths is null)
{
throw new ArgumentNullException(nameof(linkPaths));
}
var transData = TransmissionData.ReadTransmissionData(new FilePath(centralPath));
if (transData is null)
{
return;
}
// If found not the link, don't submit, otherwise throw file writing exception.
var flag = false;
foreach (var referId in transData.GetAllExternalFileReferenceIds())
{
var extRef = transData.GetLastSavedReferenceData(referId);
if (extRef.ExternalFileReferenceType != ExternalFileReferenceType.RevitLink)
{
continue;
}
var userPath = ModelPathUtils.ConvertModelPathToUserVisiblePath(extRef.GetPath());
var linkPath = linkPaths.FirstOrDefault(w => w != null && userPath.Contains(Path.GetFileName(w)));
if (linkPath is null)
{
continue;
}
var elmId = extRef.GetReferencingId();
transData.SetDesiredReferenceData(elmId, new FilePath(linkPath), PathType.Relative, true);
flag = true;
}
if (!flag)
{
return;
}
transData.IsTransmitted = true;
TransmissionData.WriteTransmissionData(new FilePath(centralPath), transData);
}
/// <summary>
/// 设置Revit链接
/// </summary>
/// <param name="doc"></param>
/// <param name="filePaths"></param>
public static void SetLinks(this Document doc, params string[] filePaths)
{
if (doc is null)
{
throw new ArgumentNullException(nameof(doc));
}
if (filePaths is null)
{
throw new ArgumentNullException(nameof(filePaths));
}
foreach (var filePath in filePaths)
{
if (!File.Exists(filePath))
{
throw new FileNotFoundException(filePath);
}
// main elementFunc modifies repeatedly, so the performance is poor.
var linkTypes = doc.OfClass<RevitLinkType>().Where(w => filePath.Contains(w.Name));
if (linkTypes.FirstOrDefault(f => f.Name.Split('-').Length == 5) is not RevitLinkType type)
{
return;
}
type.LoadFrom(new FilePath(filePath), new WorksetConfiguration(WorksetConfigurationOption.OpenLastViewed));
type.PathType = PathType.Relative;
}
}
/// <summary>
/// 移除0长度标注
/// </summary>
/// <param name="dimension"></param>
/// <param name="referenceArray"></param>
/// <returns></returns>
public static bool TryRemoveZeroes(this Dimension dimension, out ReferenceArray referenceArray)
{
referenceArray = new ReferenceArray();
var document = dimension.Document;
var isEmpty = dimension.Segments.IsEmpty;
if (isEmpty)
{
return false;
}
else
{
for (var i = 0; i < dimension.NumberOfSegments; i++)
{
var dimensionSegment = dimension.Segments.get_Item(i);
var value = dimensionSegment.Value;
if (!(value != null && Math.Abs(value.Value) < 0.0001))
{
var isEmpty2 = referenceArray.IsEmpty;
if (isEmpty2)
{
var refer = dimension.References.get_Item(i);
var element = document.GetElement(refer);
if (element is Grid or Level)
{
refer = new Reference(element);
}
referenceArray.Append(refer);
}
var refer1 = dimension.References.get_Item(i + 1);
var element1 = document.GetElement(refer1);
if (element1 is Grid or Level)
{
refer1 = new Reference(element1);
}
referenceArray.Append(refer1);
}
}
return referenceArray.Size < dimension.References.Size;
}
}
/// <summary>
/// 隐藏或者显示图层
/// </summary>
/// <param name="doc"></param>
/// <param name="reference"></param>
/// <param name="bl">tr是显示 false是隐藏</param>
public static void VisLayer(this Document doc, Reference reference, bool bl)
{
var element = doc.GetElement(reference);
//GeometryElement geoElem = elementFunc.get_Geometry(new Options()); //几何图元
var geoObj = element.GetGeometryObjectFromReference(reference); //几何对象
if (geoObj.GraphicsStyleId != ElementId.InvalidElementId)
{
if (doc.GetElement(geoObj.GraphicsStyleId) is GraphicsStyle gs)
{
var targetCategory = gs.GraphicsStyleCategory;
doc.ActiveView.SetCategoryHidden(targetCategory.Id, bl);
}
}
}
/// <summary>
/// 发光材质
/// </summary>
/// <param name="doc"></param>
public static void GetIllumMaterial(this Document doc)
{
var materials = doc.OfClass<Material>().Cast<Material>();
StringBuilder sb = new();
foreach (var material in materials)
{
if (doc.GetElement(material.AppearanceAssetId) is AppearanceAssetElement assetElem)
{
var asset = assetElem.GetRenderingAsset();
var prop = asset.FindByName("generic_self_illum_luminance");
var d = prop as AssetPropertyDouble;
if (d?.Value > 0)
{
sb.AppendLine(material.Name);
}
}
}
}
/// <summary>
/// 射线法查找所有的Element
/// </summary>
/// <param name="doc">Dcument</param>
/// <param name="filter">例如ElementClassFilter filter = new ElementClassFilter(typeof(CableTray))</param>
/// <param name="targetRef">目标对象</param>
/// <param name="center">射源</param>
/// <param name="direction">方向</param>
/// <returns>返回该射线</returns>
public static IList<Element> XRayFindAll(
this Document doc,
ElementFilter filter,
FindReferenceTarget targetRef,
XYZ center,
XYZ direction
)
{
var view3D = doc.OfClass<View3D>().Cast<View3D>().First(v3 => !v3.IsTemplate);
var refWithContexts = new ReferenceIntersector(filter, targetRef, view3D).Find(center, direction);
if (refWithContexts == null)
{
return null;
}
var resultElements = new List<Element>();
foreach (var rwc in refWithContexts)
{
var reference = rwc.GetReference();
var hitElement = doc.GetElement(reference);
if (hitElement != null)
{
resultElements.Add(hitElement);
}
}
return resultElements;
}
/// <summary>
/// 射线法查找最近的Element
/// </summary>
/// <param name="doc"></param>
/// <param name="filter">例如ElementClassFilter filter = new ElementClassFilter(typeof(CableTray))</param>
/// <param name="targetRef">目标对象</param>
/// <param name="center">射源</param>
/// <param name="direction">方向</param>
/// <param name="hitElement">被击中的Element</param>
/// <returns>返回该射线</returns>
public static Line XRayFindNearest(
this Document doc,
ElementFilter filter,
FindReferenceTarget targetRef,
XYZ center,
XYZ direction,
ref Element hitElement
)
{
var view3D = doc
.OfClass<View3D>()
.Cast<View3D>()
.First(v3 => !v3.IsTemplate);
ReferenceIntersector refIntersector = new(filter, targetRef, view3D);
var rwc = refIntersector.FindNearest(center, direction);
if (rwc == null)
{
return null;
}
var reference = rwc.GetReference();
var intersection = reference.GlobalPoint;
hitElement = doc.GetElement(reference);
Line result = null;
if (!center.IsAlmostEqualTo(intersection))
{
result = Line.CreateBound(center, intersection);
}
else
{
hitElement = null;
}
return result;
}
#if REVIT2021
/// <summary>
/// 修改测量点
/// </summary>
/// <param name="doc"></param>
public static void ResetBasePoint(this Document doc)
{
var surveyPoint = BasePoint.GetSurveyPoint(doc);
var pos = surveyPoint.Position;
var sharedPos = surveyPoint.SharedPosition;
//surveyPoint.Position.Subtract(pos);
var projectBasePoint = BasePoint.GetProjectBasePoint(doc);
var pos1 = projectBasePoint.Position;
var sharePos1 = projectBasePoint.SharedPosition;
using (Transaction trans = new(doc, "移动测量点"))
{
trans.Start();
ElementTransformUtils.MoveElement(doc, surveyPoint.Id, sharedPos.Negate());
doc.Regenerate();
ElementTransformUtils.MoveElement(doc, surveyPoint.Id, pos.Negate());
ElementTransformUtils.MoveElement(doc, projectBasePoint.Id, pos1.Negate());
projectBasePoint.get_Parameter(BuiltInParameter.BASEPOINT_ANGLETON_PARAM).Set(0);
trans.Commit();
}
if (
!(
surveyPoint.SharedPosition.IsAlmostEqualTo(XYZ.Zero)
&& projectBasePoint.SharedPosition.IsAlmostEqualTo(XYZ.Zero)
)
)
{
MessageBox.Show("请修改测量点的裁剪状态", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
#endif
}