C#代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.Revit.UI; using Autodesk.Revit.DB; using Autodesk.Revit.Attributes; using Autodesk.Revit.UI.Selection; using Autodesk.Revit.DB.Plumbing; namespace StudentRevit { [TransactionAttribute(TransactionMode.Manual)] [RegenerationAttribute(RegenerationOption.Manual)] public class Class1 : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIDocument uidoc = commandData.Application.ActiveUIDocument; Document doc = uidoc.Document; Selection sel = uidoc.Selection; //让用户选择一个点或一个元素 //第二个参数,ISelectionFilter,这个点必须符合这个过滤器的 Reference r = sel.PickObject(ObjectType.PointOnElement, new PipeFilter()); //获取到这一点 XYZ firstPos = r.GlobalPoint; //获取第二点 r = sel.PickObject(ObjectType.PointOnElement, new PipeFilter()); XYZ secondPos = r.GlobalPoint; //获取管道Pipe Pipe pipe = doc.GetElement(r) as Pipe; //获取位置曲线 LocationCurve locationCurve =pipe.Location as LocationCurve; //获取这个线的第一个点 XYZ startPoint=locationCurve.Curve.GetEndPoint(0); //获取这个线的第二个点 XYZ endPoint =locationCurve.Curve.GetEndPoint(1); //GetNearXYZ:获取最近的哪一点;Project:在这条曲线上投射指定的点 XYZ pos1 =locationCurve.Curve.Project(GetNearXYZ(startPoint, firstPos, secondPos)).XYZPoint; XYZ pos2=locationCurve.Curve.Project(GetNearXYZ(endPoint, firstPos, secondPos)).XYZPoint; //using (Transaction trans=new Transaction(doc,"相邻点坐标")) //{ // trans.Start(); // locationCurve.Curve = Line.CreateBound(startPoint,pos1); // //将管子拷贝一份 // ElementId newElemId = ElementTransformUtils.CopyElement(doc, pipe.Id, new XYZ(0, 0, 0)).FirstOrDefault(); // Element newPipe = doc.GetElement(newElemId); // (newPipe.Location as LocationCurve).Curve = Line.CreateBound(endPoint, pos2); // trans.Commit(); //} List<Line> line_list = GenerateLines(startPoint,endPoint,firstPos,secondPos,100); using (Transaction trans=new Transaction(doc,"相邻点坐标")) { trans.Start(); foreach (Line line in line_list) { ElementId newElemId = ElementTransformUtils.CopyElement(doc, pipe.Id, XYZ.Zero).FirstOrDefault(); Pipe newPipe = doc.GetElement(newElemId) as Pipe; (newPipe.Location as LocationCurve).Curve = line; } doc.Delete(pipe.Id); trans.Commit(); } return Result.Succeeded; } private List<Line> GenerateLines(XYZ startPoint, XYZ endPoint, XYZ firstPos, XYZ secondPos, int offset) { List<Line> line_list = new List<Line>(); Line projLine=Line.CreateBound(startPoint, endPoint); XYZ near = GetNearXYZ(startPoint, firstPos, secondPos); XYZ pos1 = projLine.Project(near).XYZPoint; line_list.Add(Line.CreateBound(pos1, startPoint)); near = GetNearXYZ(endPoint, firstPos, secondPos); XYZ pos2 = projLine.Project(near).XYZPoint; line_list.Add(Line.CreateBound(pos2, endPoint)); XYZ offsetPos1=pos1+new XYZ(0,0, offset); line_list.Add(Line.CreateBound(pos1, offsetPos1)); XYZ offsetPos2=pos2+new XYZ(0,0, offset); line_list.Add(Line.CreateBound(pos2, offsetPos2)); line_list.Add(Line.CreateBound(offsetPos1,offsetPos2)); return line_list; } /// <summary> /// 选择元素过滤器,过滤出管道(Pipe),===》用户只能选择管道的元素 /// </summary> public class PipeFilter : ISelectionFilter { public bool AllowElement(Element elem) { //如果是管道(Pipe)返回true,否则false return elem is Pipe; } public bool AllowReference(Reference reference, XYZ position) { return true; } } /// <summary> /// 获取最近的相邻点坐标 /// </summary> /// <param name="current">当前点</param> /// <param name="first">选择的第一个点坐标</param> /// <param name="second">选择的第二个点坐标</param> /// <returns></returns> public XYZ GetNearXYZ(XYZ current,XYZ first,XYZ second) { //DistanceTo:返回从该点到指定点的距离。 return first.DistanceTo(current) > second.DistanceTo(current) ? second : first; } } }
演示
完整代码,解决弯管问题
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.Revit.UI; using Autodesk.Revit.DB; using Autodesk.Revit.Attributes; using Autodesk.Revit.UI.Selection; using Autodesk.Revit.DB.Plumbing; namespace StudentRevit { [TransactionAttribute(TransactionMode.Manual)] [RegenerationAttribute(RegenerationOption.Manual)] public class Class1 : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIDocument uidoc = commandData.Application.ActiveUIDocument; Document doc = uidoc.Document; Selection sel = uidoc.Selection; //让用户选择一个点或一个元素 //第二个参数,ISelectionFilter,这个点必须符合这个过滤器的 Reference r = sel.PickObject(ObjectType.PointOnElement, new PipeFilter()); //获取到这一点 XYZ firstPos = r.GlobalPoint; //获取第二点 r = sel.PickObject(ObjectType.PointOnElement, new PipeFilter()); XYZ secondPos = r.GlobalPoint; //获取管道Pipe Pipe pipe = doc.GetElement(r) as Pipe; //获取位置曲线 LocationCurve locationCurve =pipe.Location as LocationCurve; //获取这个线的第一个点 XYZ startPoint=locationCurve.Curve.GetEndPoint(0); //获取这个线的第二个点 XYZ endPoint =locationCurve.Curve.GetEndPoint(1); //GetNearXYZ:获取最近的哪一点;Project:在这条曲线上投射指定的点 XYZ pos1 =locationCurve.Curve.Project(GetNearXYZ(startPoint, firstPos, secondPos)).XYZPoint; XYZ pos2=locationCurve.Curve.Project(GetNearXYZ(endPoint, firstPos, secondPos)).XYZPoint; //using (Transaction trans=new Transaction(doc,"相邻点坐标")) //{ // trans.Start(); // locationCurve.Curve = Line.CreateBound(startPoint,pos1); // //将管子拷贝一份 // ElementId newElemId = ElementTransformUtils.CopyElement(doc, pipe.Id, new XYZ(0, 0, 0)).FirstOrDefault(); // Element newPipe = doc.GetElement(newElemId); // (newPipe.Location as LocationCurve).Curve = Line.CreateBound(endPoint, pos2); // trans.Commit(); //} List<Line> line_list = GenerateLines(startPoint,endPoint,firstPos,secondPos,100); List<Pipe> pipe_list = new List<Pipe>(); using (Transaction trans=new Transaction(doc,"相邻点坐标")) { trans.Start(); foreach (Line line in line_list) { ElementId newElemId = ElementTransformUtils.CopyElement(doc, pipe.Id, XYZ.Zero).FirstOrDefault(); Pipe newPipe = doc.GetElement(newElemId) as Pipe; (newPipe.Location as LocationCurve).Curve = line; pipe_list.Add(newPipe); } doc.Delete(pipe.Id); trans.Commit(); } //获取所有连接器 List<Connector> cons = new List<Connector>(); foreach (Pipe newPipe in pipe_list) { ConnectorSet connectorSet=newPipe.ConnectorManager.Connectors; foreach (var conn in connectorSet) { cons.Add(conn as Connector); } } for (int i = cons.Count-1; i >0; i--) { Connector conn = cons[i]; Connector connectTo = GetConnector(conn, cons); if (connectTo != null) { using (Transaction trans = new Transaction(doc, "create elbow")) { trans.Start(); doc.Create.NewElbowFitting(conn, connectTo); trans.Commit(); } } } return Result.Succeeded; } public Connector GetConnector(Connector currentCon,List<Connector> connectors) { foreach (Connector con in connectors) { if (con.Origin.IsAlmostEqualTo(currentCon.Origin)&&con.Owner.Id!=currentCon.Owner.Id) { return con; } } return null; } private List<Line> GenerateLines(XYZ startPoint, XYZ endPoint, XYZ firstPos, XYZ secondPos, int offset) { List<Line> line_list = new List<Line>(); Line projLine=Line.CreateBound(startPoint, endPoint); XYZ near = GetNearXYZ(startPoint, firstPos, secondPos); XYZ pos1 = projLine.Project(near).XYZPoint; line_list.Add(Line.CreateBound(pos1, startPoint)); near = GetNearXYZ(endPoint, firstPos, secondPos); XYZ pos2 = projLine.Project(near).XYZPoint; line_list.Add(Line.CreateBound(pos2, endPoint)); XYZ offsetPos1=pos1+new XYZ(0,0, offset); line_list.Add(Line.CreateBound(pos1, offsetPos1)); XYZ offsetPos2=pos2+new XYZ(0,0, offset); line_list.Add(Line.CreateBound(pos2, offsetPos2)); line_list.Add(Line.CreateBound(offsetPos1,offsetPos2)); return line_list; } /// <summary> /// 选择元素过滤器,过滤出管道(Pipe),===》用户只能选择管道的元素 /// </summary> public class PipeFilter : ISelectionFilter { public bool AllowElement(Element elem) { //如果是管道(Pipe)返回true,否则false return elem is Pipe; } public bool AllowReference(Reference reference, XYZ position) { return true; } } /// <summary> /// 获取最近的相邻点坐标 /// </summary> /// <param name="current">当前点</param> /// <param name="first">选择的第一个点坐标</param> /// <param name="second">选择的第二个点坐标</param> /// <returns></returns> public XYZ GetNearXYZ(XYZ current,XYZ first,XYZ second) { //DistanceTo:返回从该点到指定点的距离。 return first.DistanceTo(current) > second.DistanceTo(current) ? second : first; } } }