You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:45:34