AEC DevBlog(Revit 二次开发)- 使用 Revit API 选取三维点
原文链接:Picking 3D points using Revit API
作为 Revit 二次开发人员,我们很熟悉如何使用 Selection.PickPoint() 在二维平面上选取一个点。由于 Revit API 并不直接支持在三维坐标系中选取一个点,我们需要采用稍微复杂一点儿的方法来实现:
1. 首先借助 View.SketchPlane 属性设置当前工作平面;
2. 然后使用 Selection.PickPoint() 在当前工作平面上选取点
代码如下:
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]public class Command : IExternalCommand{ public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData,ref string message, Autodesk.Revit.DB.ElementSet elements){UIApplication uiapp = commandData.Application;UIDocument uidoc = uiapp.ActiveUIDocument;Application app = uiapp.Application;Document doc = uidoc.Document;XYZ point_in_3d;if (SetWorkPlaneAndPickObject(uidoc, out point_in_3d)){TaskDialog.Show("3D Point Selected","3D point picked on the plane"+ " defined by the selected face: "+ "X: " + point_in_3d.X.ToString()+ ", Y: " + point_in_3d.Y.ToString()+ ", Z: " + point_in_3d.Z.ToString());return Result.Succeeded;}else{message = "3D point selection failed";return Result.Failed;}}/// <summary>/// 返回一个三维坐标系中的点// 用户首先被要求选取某个元素的一个面(工作平面),然后用户在这个面上选取一个点/// </summary>public bool SetWorkPlaneAndPickObject(UIDocument uidoc,out XYZ point_in_3d){point_in_3d = null;Document doc = uidoc.Document;Reference r = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Face,"Please select a planar face to define work plane");Element e = doc.GetElement(r.ElementId); if (null != e){PlanarFace face = e.GetGeometryObjectFromReference(r)as PlanarFace;GeometryElement geoEle = e.get_Geometry(new Options());Transform transform = null;// 译者注:这段代码应该是基于 Revit 2012。在 Revit 2013 中,geoEle 本身就实现了 IEnumerable 接口,所以直接使用 geoEle 遍历即可foreach (GeometryObject gObj in geoEle.Objects){GeometryInstance gInst = gObj as GeometryInstance;if (null != gInst){transform = gInst.Transform;}}if (face != null){Plane plane = null;// 译者注:这个 transform 很关键。它是表示元素自身的坐标系和当前文档的坐标系是否有差异。// 因为面的法线向量和面的原点的值都是基于元素自身的坐标系的。如果元素自身的坐标系和当前文档的坐标系有差异,则我们必须使用// 坐标系差异(transform)来将面的法线向量和面的原点的值转换成基于当前文档坐标系的值。if (null != transform){plane = new Plane(transform.OfVector(face.Normal), transform.OfPoint(face.Origin));}else{plane = new Plane(face.Normal, face.Origin);}Transaction t = new Transaction(doc);t.Start("Temporarily set work plane to pick point in 3D");SketchPlane sp = doc.Create.NewSketchPlane(plane);uidoc.ActiveView.SketchPlane = sp;uidoc.ActiveView.ShowActiveWorkPlane();try{point_in_3d = uidoc.Selection.PickPoint("Please pick a point on the plane defined by the selected face");}catch (OperationCanceledException){}// 译者注:回滚事务意味着之前创建的草图平面(SketchPlane)也自动被删除了t.RollBack();}}return null != point_in_3d;}