AutoCAD VB.NET按参考角旋转组对象时参考角恒为0问题求助
问题根因
- 代码中虽然声明了
RefAngle参考角变量,但旋转逻辑完全没有调用该参数,传入旋转矩阵的角度只有NewAngle,参考角始终未参与计算,等价于默认参考角为0。 - 所有数值类参数(基点坐标、角度)直接通过
GetString获取字符串后强转数值,没有做输入合法性校验,输入非数字内容会直接抛错,也没有利用AutoCAD编辑器自带的数值输入交互能力。 - 输入的基点坐标未做UCS到WCS的坐标系转换,自定义UCS场景下旋转基点位置会偏移。
- 存在无效变量:声明的
btr块表记录对象全程未使用,属于冗余代码;提示文本存在拼写错误,Refence Angle正确拼写为Reference Angle。
参考角旋转实现逻辑
AutoCAD 参考角旋转的核心是计算角度差值:实际需要旋转的角度 = 输入的新角度 - 输入的参考角。例如参考角为45°、目标新角度为90°时,对象实际只需要旋转45°即可对齐到目标角度。
修正后代码
<CommandMethod("ROTATEGROUP")> Public Shared Sub ROTATEGROUP() Dim doc As Document = AutoCADApp.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Using tr As Transaction = db.TransactionManager.StartTransaction() ' 获取组名 Dim groupRes = ed.GetString(vbLf & "输入组名: ") If groupRes.Status <> PromptStatus.OK Then Return Dim groupName As String = groupRes.StringResult ' 获取旋转基点(用GetDouble直接获取数值,自带输入校验) Dim xRes = ed.GetDouble(vbLf & "输入基点X坐标: ") If xRes.Status <> PromptStatus.OK Then Return Dim yRes = ed.GetDouble(vbLf & "输入基点Y坐标: ") If yRes.Status <> PromptStatus.OK Then Return Dim zRes = ed.GetDouble(vbLf & "输入基点Z坐标: ") If zRes.Status <> PromptStatus.OK Then Return ' 获取角度(角度转弧度) Dim refAngleRes = ed.GetDouble(vbLf & "输入参考角(度): ") If refAngleRes.Status <> PromptStatus.OK Then Return Dim newAngleRes = ed.GetDouble(vbLf & "输入目标新角度(度): ") If newAngleRes.Status <> PromptStatus.OK Then Return ' 角度转弧度 + 计算实际旋转角度差 Dim refAngleRad As Double = refAngleRes.Value * (Math.PI / 180) Dim newAngleRad As Double = newAngleRes.Value * (Math.PI / 180) Dim actualRotAngle As Double = newAngleRad - refAngleRad ' 打开组字典获取目标组 Dim gd As DBDictionary = CType(tr.GetObject(db.GroupDictionaryId, OpenMode.ForRead), DBDictionary) If Not gd.Contains(groupName) Then ed.WriteMessage(vbLf & "错误:指定名称的组不存在") Return End If Dim grpId As ObjectId = gd.GetAt(groupName) Dim grp As Group = CType(tr.GetObject(grpId, OpenMode.ForWrite), Group) Dim ids As ObjectId() = grp.GetAllEntityIds() ' 处理坐标系:将用户输入的UCS坐标转为WCS坐标,适配旋转矩阵计算 Dim curUCSMatrix As Matrix3d = ed.CurrentUserCoordinateSystem Dim baseUcsPt As New Point3d(xRes.Value, yRes.Value, zRes.Value) Dim baseWcsPt As Point3d = baseUcsPt.TransformBy(curUCSMatrix.Inverse()) Dim rotAxis As Vector3d = curUCSMatrix.CoordinateSystem3d.Zaxis.TransformBy(curUCSMatrix.Inverse()) ' 遍历组内实体执行旋转 For Each entId As ObjectId In ids Dim ent As Entity = CType(tr.GetObject(entId, OpenMode.ForWrite), Entity) ent.TransformBy(Matrix3d.Rotation(actualRotAngle, rotAxis, baseWcsPt)) Next tr.Commit() ed.WriteMessage(vbLf & "组旋转完成") End Using End Sub
额外优化点
- 所有交互输入增加了退出判断,用户按ESC可以直接终止命令,不会抛异常。
- 增加了组名存在性校验,输入不存在的组名时会给出明确提示,不会触发崩溃。
- 所有数值输入改用
GetDouble方法,AutoCAD会自动校验输入合法性,支持用户直接在绘图区点选输入,不需要手动输入数值。 - 坐标系转换逻辑补全,无论当前UCS怎么设置,旋转基点和旋转轴都和用户输入的预期一致。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

