Files

1380 lines
45 KiB
C#
Raw Permalink Normal View History

2025-07-11 09:20:23 +08:00
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows;
using Autodesk.Revit.DB;
2025-04-24 20:56:44 +08:00
using Autodesk.Revit.UI;
2026-02-21 16:31:24 +08:00
using Autodesk.Revit.DB.Visual;
using ShrlAlgoToolkit.RevitCore.Assists;
2025-04-24 20:56:44 +08:00
2026-02-21 16:31:24 +08:00
namespace ShrlAlgoToolkit.RevitCore.Extensions;
2024-09-22 11:05:41 +08:00
2025-12-28 11:47:54 +08:00
public static class DocumentExtensions
2024-09-22 11:05:41 +08:00
{
/// <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>
2026-02-22 20:03:42 +08:00
/// 按名称修改所有过滤器颜色
/// </summary>
/// <param name="doc"></param>
/// <param name="filterName">过滤器名称</param>
public static void ModifyFilter(this Document doc, string filterName,Color color)
{
var templates = doc.OfClass<View>().Cast<View>().Where(v => v.IsTemplate);
foreach (var template in templates)
{
var filters = template.GetFilters();
foreach (var id in filters)
{
var filterElement = doc.GetElement(id);
if (filterElement is ParameterFilterElement filter)
{
if (filter.Name.Contains(filterName))
{
var ogs = new OverrideGraphicSettings();
ogs.SetProjectionLineColor(color);
ogs.SetProjectionLineColor(color);
ogs.SetProjectionLineColor(color);
ogs.SetProjectionLineColor(color);
template.SetFilterOverrides(id, ogs);
}
}
}
}
}
/// <summary>
2024-09-22 11:05:41 +08:00
/// 获取所有可预览视图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))
{
2025-07-11 09:20:23 +08:00
doc.LoadFamily(familyPath, new DefaultFamilyLoadOptions(), out family);
2024-09-22 11:05:41 +08:00
}
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();
}
}
}
2025-07-11 09:20:23 +08:00
/// <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;
}
2024-09-22 11:05:41 +08:00
/// <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
}