VB.NET:如何获取不含贝塞尔手柄位置的GraphicsPath边界
问题
需要为GraphicsPath创建边界框以实现群组尺寸调整:
- 使用直线点时,选择矩形表现正常;
- 转换为贝塞尔曲线后,选择矩形会包含贝塞尔手柄位置,导致尺寸远大于预期;
- 当前遍历PathPoints计算边界的方式会包含手柄点,改用原始点数组又无法适配贝塞尔曲线的弧度,寻求简单解决方法。
现有代码
Public Overrides Sub DrawSelectionRectangle(ByVal g As Graphics) SelectionRectangle = New RectangleF(0, 0, 0, 0) Dim GP As GraphicsPath = _lastGp 'DAVE If GP IsNot Nothing Then If _lastGp.PointCount > 1 Then Try Dim BH As New Single : Dim TH As New Single : Dim LW As New Single : Dim RW As New Single TH = GP.PathPoints(0).Y LW = GP.PathPoints(0).X For i = 0 To GP.PathPoints.Length - 1 With GP.PathPoints(i) If .Y < TH Then TH = .Y If .X < LW Then LW = .X If .Y > BH Then BH = .Y If .X > RW Then RW = .X End With Next i 'DAVE - This code won't work as it doesn't factor in for space made by the actual bezier curves, GP path must be followed. BUT! this is a tidier solution. 'SelectionRectangle = New RectangleF(0, 0, 0, 0) 'If _pointArray IsNot Nothing Then ' If _pointArray.Count > 1 Then ' Try ' Dim BH As New Single : Dim TH As New Single : Dim LW As New Single : Dim RW As New Single ' LW = _pointArray(0).P.X ' TH = _pointArray(0).P.Y ' For i = 0 To _pointArray.Count - 1 ' With _pointArray(i).P ' If .Y < TH Then TH = .Y ' If .X < LW Then LW = .X ' If .Y > BH Then BH = .Y ' If .X > RW Then RW = .X ' End With ' Next i '================================= SelectionRectangle = New RectangleF(New PointF(LW, TH), New SizeF(RW - LW, BH - TH)) Dim r As RectangleF = DrawRectangle.GetNormalizedRectangle(SelectionRectangle) Dim gpen As Pen = New Pen(Color.Gray, MyBase.StrokeWidth) gpen.DashStyle = DashStyle.Dash g.DrawRectangle(gpen, r.X, r.Y, r.Width, r.Height) gpen.Dispose() Catch ex As Exception ErrH.Log("DrawSelectionRectangle", "Draw", ex.ToString(), ErrH._LogPriority.Info) End Try End If End If End Sub
解决方案
直接使用GraphicsPath内置的GetBounds()方法,该方法会自动计算路径实际绘制区域的边界框:
- 忽略贝塞尔手柄的位置,只考虑曲线实际覆盖的范围;
- 无需手动遍历点或处理曲线逻辑,代码更简洁可靠。
修改后的代码如下:
Public Overrides Sub DrawSelectionRectangle(ByVal g As Graphics) SelectionRectangle = New RectangleF(0, 0, 0, 0) Dim GP As GraphicsPath = _lastGp 'DAVE If GP IsNot Nothing Then If _lastGp.PointCount > 1 Then Try ' 直接调用GetBounds获取实际边界框 SelectionRectangle = GP.GetBounds() Dim r As RectangleF = DrawRectangle.GetNormalizedRectangle(SelectionRectangle) Dim gpen As Pen = New Pen(Color.Gray, MyBase.StrokeWidth) gpen.DashStyle = DashStyle.Dash g.DrawRectangle(gpen, r.X, r.Y, r.Width, r.Height) gpen.Dispose() Catch ex As Exception ErrH.Log("DrawSelectionRectangle", "Draw", ex.ToString(), ErrH._LogPriority.Info) End Try End If End If End Sub
内容的提问来源于stack exchange,提问作者CNC3D
相关产品推荐
相关产品推荐

