功能更新
This commit is contained in:
194
ShrlAlgo.Addin.Test/AlignMEPCurvesToSlabCmd.cs
Normal file
194
ShrlAlgo.Addin.Test/AlignMEPCurvesToSlabCmd.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Electrical;
|
||||
using Autodesk.Revit.DB.Plumbing;
|
||||
using Autodesk.Revit.UI;
|
||||
using Autodesk.Revit.UI.Selection;
|
||||
|
||||
namespace ShrlAlgo.Addin.Test
|
||||
{
|
||||
/// <summary>
|
||||
/// Revit执行命令
|
||||
/// </summary>
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class AlignMEPCurvesToSlabCmd : IExternalCommand
|
||||
{
|
||||
public void AlignMEPCurveToSlab(Document doc, MEPCurve mepCurve, Floor slab)
|
||||
{
|
||||
// 1. 获取管线的定位曲线
|
||||
LocationCurve locationCurve = mepCurve.Location as LocationCurve;
|
||||
if (locationCurve == null) return;
|
||||
|
||||
Curve curve = locationCurve.Curve;
|
||||
XYZ startPoint = curve.GetEndPoint(0);
|
||||
XYZ endPoint = curve.GetEndPoint(1);
|
||||
|
||||
View3D view3D = doc.ActiveView as View3D;
|
||||
if (view3D == null)
|
||||
{
|
||||
// 尝试获取第一个非模板的3D视图
|
||||
FilteredElementCollector collector = new FilteredElementCollector(doc);
|
||||
view3D = collector.OfClass(typeof(View3D))
|
||||
.Cast<View3D>()
|
||||
.FirstOrDefault(v => !v.IsTemplate);
|
||||
}
|
||||
// 注意:实际开发中最好手动指定一个确定的3D视图,这里为了演示简单取了第一个非模板视图
|
||||
|
||||
if (view3D == null) return; // 如果没有3D视图无法进行
|
||||
|
||||
// 2.2 直接传入 slab.Id,表示只与这个元素做碰撞检测
|
||||
ReferenceIntersector intersector = new ReferenceIntersector(slab.Id, FindReferenceTarget.Element, view3D);
|
||||
intersector.FindReferencesInRevitLinks = false;
|
||||
var level= doc.GetElement(slab.LevelId) as Level;
|
||||
var offsetInFeet = ((Line)locationCurve.Curve).Origin.Z - level.Elevation;
|
||||
|
||||
// 3. 计算新的起点和终点
|
||||
XYZ newStart = GetProjectedPoint(intersector, startPoint, offsetInFeet);
|
||||
XYZ newEnd = GetProjectedPoint(intersector, endPoint, offsetInFeet);
|
||||
|
||||
if (newStart == null || newEnd == null) return; // 投影失败
|
||||
|
||||
// 4. 更新管线位置
|
||||
using (Transaction t = new Transaction(doc, "管线对齐楼板"))
|
||||
{
|
||||
t.Start();
|
||||
//if (mepCurve is CableTray)
|
||||
//{
|
||||
// DisconnectMEPCurve(mepCurve);
|
||||
//}
|
||||
doc.Regenerate();
|
||||
// 断开连接的逻辑建议加上,避免报错
|
||||
|
||||
// 创建新直线
|
||||
Line newLine = Line.CreateBound(newStart, newEnd);
|
||||
locationCurve.Curve = newLine;
|
||||
|
||||
t.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:获取投影后的点
|
||||
private XYZ GetProjectedPoint(ReferenceIntersector intersector, XYZ point, double offset)
|
||||
{
|
||||
// 从高处向下投射,或者从点的位置向下/向上投射
|
||||
// 这里假设管线在板上方,向下投射 (-Z)
|
||||
XYZ rayOrigin = new XYZ(point.X, point.Y, point.Z + 100); // 抬高起点确保能射到
|
||||
XYZ rayDirection = XYZ.BasisZ.Negate(); // 向下
|
||||
|
||||
ReferenceWithContext context = intersector.FindNearest(rayOrigin, rayDirection);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
Reference refer = context.GetReference();
|
||||
XYZ intersectionPoint = refer.GlobalPoint;
|
||||
|
||||
// 关键:新的Z值 = 板表面交点Z + 偏移量
|
||||
return new XYZ(point.X, point.Y, intersectionPoint.Z + offset);
|
||||
}
|
||||
|
||||
return null; // 未找到交点
|
||||
}
|
||||
|
||||
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
|
||||
{
|
||||
var uiApp = commandData.Application;
|
||||
var UiDocument = uiApp.ActiveUIDocument;
|
||||
var Document = UiDocument.Document;
|
||||
try
|
||||
{
|
||||
var curves = UiDocument.Selection.PickElementsByRectangle(new MEPCurveFilter(), "请选择需要对齐的管道")
|
||||
.OfType<MEPCurve>()
|
||||
.ToList();
|
||||
var reference = UiDocument.Selection.PickObject(ObjectType.Element, new FloorSelectionFilter(), "请选择楼板");
|
||||
var slab = Document.GetElement(reference);
|
||||
using(TransactionGroup tg=new TransactionGroup(Document, "管线对齐楼板"))
|
||||
{
|
||||
tg.Start();
|
||||
foreach (var curve in curves)
|
||||
{
|
||||
AlignMEPCurveToSlab(Document, curve, slab as Floor);
|
||||
}
|
||||
tg.Assimilate();
|
||||
}
|
||||
|
||||
return Result.Succeeded;
|
||||
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
|
||||
{
|
||||
// 用户取消选择,正常退出
|
||||
return Result.Cancelled;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 断开管线/风管的所有物理连接
|
||||
/// </summary>
|
||||
/// <param name="mepCurve">需要断开的管线</param>
|
||||
private void DisconnectMEPCurve(MEPCurve mepCurve)
|
||||
{
|
||||
// 获取连接管理器
|
||||
ConnectorManager cm = mepCurve.ConnectorManager;
|
||||
|
||||
// 遍历该管线自带的所有连接器
|
||||
foreach (Connector connector in cm.Connectors)
|
||||
{
|
||||
// 如果该端口没有连接,则跳过
|
||||
if (!connector.IsConnected) continue;
|
||||
|
||||
// 获取该端口连接到的所有“其他连接器”
|
||||
// AllRefs 包含了与之连接的所有对象(包括物理连接和逻辑系统连接)
|
||||
ConnectorSet connectedRefs = connector.AllRefs;
|
||||
|
||||
foreach (Connector otherConnector in connectedRefs)
|
||||
{
|
||||
// 排除自身(虽然很少见,但为了安全)
|
||||
if (otherConnector.Owner.Id == mepCurve.Id) continue;
|
||||
|
||||
// 过滤:只断开物理连接(End或Curve类型),保留逻辑连接通常不影响移动,
|
||||
// 但为了防止移动报错,通常建议断开物理连接。
|
||||
// 这里的判断可以根据需要放宽,直接断开所有也行。
|
||||
if (otherConnector.ConnectorType == ConnectorType.End ||
|
||||
otherConnector.ConnectorType == ConnectorType.Curve ||
|
||||
otherConnector.ConnectorType == ConnectorType.Physical)
|
||||
{
|
||||
// 执行断开操作
|
||||
connector.DisconnectFrom(otherConnector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class MEPCurveFilter : ISelectionFilter
|
||||
{
|
||||
public bool AllowElement(Element elem)
|
||||
{
|
||||
return elem is MEPCurve;
|
||||
}
|
||||
|
||||
public bool AllowReference(Reference reference, XYZ position)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal class FloorSelectionFilter : ISelectionFilter
|
||||
{
|
||||
public bool AllowElement(Element elem)
|
||||
{
|
||||
return elem is Floor;
|
||||
}
|
||||
|
||||
public bool AllowReference(Reference reference, XYZ position)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,8 +133,6 @@ internal class ModifySystemTypeCmd : IExternalCommand
|
||||
// throw;
|
||||
//}
|
||||
|
||||
#region RegionName
|
||||
#endregion
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ public class TempCmd : ExternalCommand
|
||||
//var result=string.Join(";", elems.Select(e => e.Id.ToString()));
|
||||
//Clipboard.SetText(result);
|
||||
//MessageBox.Show(result);
|
||||
return;
|
||||
|
||||
//导出Revit中的所有族类别BuiltInCategory和中文名
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<!--<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
@@ -15,5 +15,5 @@
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</runtime>-->
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user