RevitAPI:关于Curve.Distance(XYZ)方法

本文探讨了在使用线性几何计算时,遇到点到直线距离计算不准确的问题,并通过实例展示了如何从线段转换为无限直线来获取正确结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天有客户问道Line.Distance(XYZ)方法有问题,返回的点到直线的距离不正确。

例如下面的图中,点到直线的距离应该是10,但是结果返回的却是14.142135623731



他的代码是这样:

var p1 = new XYZ(0, 0, 0);
var p2 = new XYZ(10, 0, 0);
var p3 = new XYZ(20, 10, 0);
Line line = Line.CreateBound(p1, p2);
StringBuilder sb = new StringBuilder();
sb.AppendLine("p3 to Line: " + line.Distance(p3));
TaskDialog.Show("distance", sb.ToString());

确实运行的结果是:

  p3 to Line: 14.142135623731


为什么不是10呢?

答案:点到直线的距离确实是10,但是这里的Line是Bound Line,也就是线段,而这里Distance()返回的距离是点到线段的距离,也就是14.14,如下图所示:



要得到正确的结果我们可以调用Line.MakeUnbound(),先把线变成Unbound,再求结果,代码如下:

    var p1 = new XYZ(0, 0, 0);
    var p2 = new XYZ(10, 0, 0);
    var p3 = new XYZ(20, 10, 0);
    Line line = Line.CreateBound(p1, p2);
    line.MakeUnbound();
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("p3 to Line: " + line.Distance(p3));
    TaskDialog.Show("distance", sb.ToString());

如此就能返回正确的结果了。


严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) CS0234 命名空间“Autodesk.Revit.UI.Events”中不存在类型或命名空间名“ViewChangedEventArgs”(是否缺少程序集引用?) 轴网定位 F:\revitDD\轴网定位\VirtualAxisCommand.cs 70 错误(活动) CS1503 参数 5: 无法从“string”转换为“Autodesk.Revit.DB.TextNoteOptions” 轴网定位 F:\revitDD\轴网定位\VirtualAxisCommand.cs 62 错误(活动) CS1503 参数 4: 无法从“Autodesk.Revit.DB.TextNoteOptions”转换为“string” 轴网定位 F:\revitDD\轴网定位\VirtualAxisCommand.cs 62 错误(活动) CS1061 “View”未包含“Transform”的定义,并且找不到可接受第一个“View”类型参数的可访问扩展方法“Transform”(是否缺少 using 指令或程序集引用?) 轴网定位 F:\revitDD\轴网定位\VirtualAxisCommand.cs 112 错误(活动) CS1061 “UIApplication”未包含“ViewChanged”的定义,并且找不到可接受第一个“UIApplication”类型参数的可访问扩展方法“ViewChanged”(是否缺少 using 指令或程序集引用?) 轴网定位 F:\revitDD\轴网定位\VirtualAxisCommand.cs 38 错误(活动) CS1061 “Location”未包含“Origin”的定义,并且找不到可接受第一个“Location”类型参数的可访问扩展方法“Origin”(是否缺少 using 指令或程序集引用?) 轴网定位 F:\revitDD\轴网定位\VirtualAxisCommand.cs 90 错误(活动) CS0122 “FloatingAxisCommand._axisLabels”不可访问,因为它具有一定的保护级别 轴网定位 F:\revitDD\轴网定位\VirtualAxisCommand.cs 134 using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using System.Collections.Generic; using System.Linq; namespace FloatingAxisLabel { [Transaction(TransactionMode.Manual)] public class FloatingAxisCommand : IExternalCommand { // 存储轴线与浮动标签的映射关系 private static Dictionary<ElementId, TextNote> _axisLabels = new Dictionary<ElementId, TextNote>(); public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiApp = commandData.Application; UIDocument uiDoc = uiApp.ActiveUIDocument; Document doc = uiDoc.Document; View activeView = doc.ActiveView; // 步骤1:获取所有轴线 FilteredElementCollector collector = new FilteredElementCollector(doc, activeView.Id); IList<Grid> grids = collector.OfClass(typeof(Grid)).Cast<Grid>().ToList(); using (Transaction trans = new Transaction(doc, "创建浮动轴号")) { trans.Start(); // 步骤2:创建浮动标签 CreateFloatingLabels(doc, activeView, grids); trans.Commit(); } // 步骤3:注册视图变化事件 uiApp.ViewChanged += OnViewChanged; return Result.Succeeded; } // 创建浮动标签 private void CreateFloatingLabels(Document doc, View view, IList<Grid> grids) { // 获取默认文本类型 ElementId textTypeId = GetDefaultTextTypeId(doc); foreach (Grid grid in grids) { // 计算标签位置(轴线中点) XYZ labelPosition = CalculateMidPoint(grid.Curve); // 创建TextNote TextNoteOptions options = new TextNoteOptions { HorizontalAlignment = HorizontalTextAlignment.Center, VerticalAlignment = VerticalTextAlignment.Middle, TypeId = textTypeId }; TextNote floatingLabel = TextNote.Create(doc, view.Id, labelPosition, options, grid.Name); // 存储映射关系 _axisLabels[grid.Id] = floatingLabel; } } // 视图变化事件处理 private void OnViewChanged(object sender, Autodesk.Revit.UI.Events.ViewChangedEventArgs e) { UIApplication uiApp = sender as UIApplication; if (uiApp == null) return; UIDocument uiDoc = uiApp.ActiveUIDocument; Document doc = uiDoc.Document; View activeView = doc.ActiveView; // 步骤4:更新所有浮动标签位置 using (Transaction trans = new Transaction(doc, "更新浮动轴号")) { trans.Start(); foreach (var pair in _axisLabels.ToList()) { Element axis = doc.GetElement(pair.Key); if (axis is Grid grid && grid.IsValidObject) { XYZ newPosition = CalculateScreenPosition(grid, activeView); pair.Value.Location.Move(newPosition - pair.Value.Location.Origin); } else // 清理无效引用 { _axisLabels.Remove(pair.Key); } } trans.Commit(); } } // 计算轴线中点(模型坐标) private XYZ CalculateMidPoint(Curve curve) { return curve.Evaluate(0.5, true); } // 计算屏幕位置(视图坐标) private XYZ CalculateScreenPosition(Grid grid, View view) { XYZ modelPoint = CalculateMidPoint(grid.Curve); return view.Transform.OfPoint(modelPoint); } // 获取默认文本类型ID private ElementId GetDefaultTextTypeId(Document doc) { return new FilteredElementCollector(doc) .OfClass(typeof(TextNoteType)) .FirstElementId(); } } // 应用关闭时清理资源 public class ApplicationEvents : IExternalApplication { public Result OnStartup(UIControlledApplication application) { return Result.Succeeded; } public Result OnShutdown(UIControlledApplication application) { FloatingAxisCommand._axisLabels.Clear(); return Result.Succeeded; } } } 代码存在问题,请帮我解决并给我一份完整的代码
最新发布
07-05
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值